PluginProbe
The Innovative Form Builder – IvyForms / 1.1.1
The Innovative Form Builder – IvyForms v1.1.1
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
ivyforms / frontend / src / composables / IvyFormAPI.ts

IvyFormAPI.ts in The Innovative Form Builder – IvyForms 1.1.1, at frontend/src/composables/IvyFormAPI.ts

163 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import * as Vue from 'vue'
2 import { markRaw, ref } from 'vue'
3 import type { Component } from 'vue'
4 import type { FieldOptionConfig } from '@/types/field-options'
5
6 export type ComponentType = Component
7
8 export interface FormSubmitData {
9 formId: number | string
10 values: Record<string, unknown>
11 nonce: string
12 postId: number | string
13 referer: string
14 }
15
16 export type BeforeFormSubmitCallback = (
17 submit: () => Promise<void>,
18 onError: (message: string) => void,
19 data: FormSubmitData,
20 ) => void | Promise<void>
21
22 export interface IvyFormAPIHooks {
23 actions: Record<string, Array<(...args: unknown[]) => void>>
24 filters: Record<string, Array<(...args: unknown[]) => unknown>>
25 fieldInit?: Array<(field: unknown, context: unknown) => void>
26 beforeSaveFields?: Array<(fields: unknown[]) => unknown[]>
27 beforeFormSubmit?: BeforeFormSubmitCallback[]
28 getTemplatePreviewField?: Array<(fieldType: string) => unknown | null>
29
30 addAction: (hook: string, cb: (...args: unknown[]) => void) => void
31 doAction: (hook: string, ...args: unknown[]) => void
32
33 addFilter: (hook: string, cb: (...args: unknown[]) => unknown) => void
34 applyFilters: <T = unknown>(hook: string, value: T, ...args: unknown[]) => T
35
36 registerFieldInit: (callback: (field: unknown, context: unknown) => void) => void
37 registerBeforeSaveFields: (callback: (fields: unknown[]) => unknown[]) => void
38 registerBeforeFormSubmit: (callback: BeforeFormSubmitCallback) => void
39
40 triggerUpdate: () => void
41 updateCounter: { value: number }
42 }
43
44 export interface IvyFormAPIFields {
45 admin: Record<string, ComponentType>
46 public: Record<string, ComponentType>
47 registerAdmin: (name: string, component: ComponentType) => void
48 registerPublic: (name: string, component: ComponentType) => void
49 }
50
51 export interface IvyFormAPIFieldOptions {
52 registry: Record<string, FieldOptionConfig>
53 register: (config: FieldOptionConfig) => void
54 unregister: (id: string) => void
55 getForFieldType: (fieldType: string, tab?: 'general' | 'advanced') => FieldOptionConfig[]
56 }
57
58 export interface IvyFormAPI {
59 fields: IvyFormAPIFields
60 hooks: IvyFormAPIHooks
61 fieldOptions: IvyFormAPIFieldOptions
62 }
63
64 const hooksUpdateCounter = ref(0)
65 const fieldOptionsRegistry: Record<string, FieldOptionConfig> = {}
66
67 const api: IvyFormAPI = {
68 fields: {
69 admin: {},
70 public: {},
71 registerAdmin(name, component) {
72 this.admin[name] = markRaw(component)
73 },
74 registerPublic(name, component) {
75 this.public[name] = markRaw(component)
76 },
77 },
78
79 hooks: {
80 actions: {},
81 filters: {},
82 fieldInit: [],
83 beforeSaveFields: [],
84 beforeFormSubmit: [],
85 updateCounter: hooksUpdateCounter,
86 addAction(hook, cb) {
87 if (!this.actions[hook]) this.actions[hook] = []
88 this.actions[hook].push(cb)
89 },
90 doAction(hook, ...args) {
91 if (this.actions[hook]) this.actions[hook].forEach((cb) => cb(...args))
92 },
93 addFilter(hook, cb) {
94 if (!this.filters[hook]) this.filters[hook] = []
95 this.filters[hook].push(cb)
96 this.triggerUpdate()
97 },
98 applyFilters(hook: string, value: unknown, ...args: unknown[]) {
99 if (!this.filters[hook]) return value
100 return this.filters[hook].reduce(
101 (v: unknown, cb: (...args: unknown[]) => unknown) => cb(v, ...args),
102 value,
103 )
104 },
105 registerFieldInit(callback) {
106 if (!this.fieldInit) this.fieldInit = []
107 this.fieldInit.push(callback)
108 },
109 registerBeforeSaveFields(callback) {
110 if (!this.beforeSaveFields) this.beforeSaveFields = []
111 this.beforeSaveFields.push(callback)
112 },
113 registerBeforeFormSubmit(callback) {
114 if (!this.beforeFormSubmit) this.beforeFormSubmit = []
115 this.beforeFormSubmit.push(callback)
116 },
117 triggerUpdate() {
118 hooksUpdateCounter.value++
119 },
120 },
121
122 fieldOptions: {
123 registry: fieldOptionsRegistry,
124 register(config: FieldOptionConfig) {
125 fieldOptionsRegistry[config.id] = markRaw(config) as FieldOptionConfig
126 api.hooks.triggerUpdate()
127 },
128 unregister(id: string) {
129 delete fieldOptionsRegistry[id]
130 api.hooks.triggerUpdate()
131 },
132 getForFieldType(fieldType: string, tab?: 'general' | 'advanced'): FieldOptionConfig[] {
133 return Object.values(fieldOptionsRegistry)
134 .filter((config) => {
135 // Filter by field type
136 if (!config.fieldTypes.includes(fieldType)) return false
137 // Filter by tab if specified
138 if (tab && config.tab && config.tab !== tab) return false
139 return true
140 })
141 .sort((a, b) => a.order - b.order)
142 },
143 },
144 }
145
146 // Ready event helpers
147 export const IVY_READY_EVENT = 'ivyforms:ready' as const
148 export function dispatchIvyReady(detail?: Record<string, unknown>) {
149 const evt = new CustomEvent(IVY_READY_EVENT, { detail })
150 window.dispatchEvent(evt)
151 document.dispatchEvent(evt)
152 }
153
154 export function installIvyGlobals() {
155 const w = window
156 if (!w.Vue) w.Vue = Vue
157 w.IvyFormsApi = api
158
159 return api
160 }
161
162 export default api
163