@narrative.io/jsonforms-provider-protocols 3.0.0-beta.3 → 3.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/projection.d.ts.map +1 -1
- package/dist/core/projection.js.map +1 -1
- package/dist/core/transforms.d.ts.map +1 -1
- package/dist/core/transforms.js +3 -1
- package/dist/core/transforms.js.map +1 -1
- package/dist/jsonforms-provider-protocols.css +2 -2
- package/dist/vue/components/ProviderAutocomplete.vue.d.ts.map +1 -1
- package/dist/vue/components/ProviderAutocomplete.vue.js +8 -5
- package/dist/vue/components/ProviderAutocomplete.vue.js.map +1 -1
- package/dist/vue/components/ProviderMultiSelect.vue.d.ts.map +1 -1
- package/dist/vue/components/ProviderMultiSelect.vue.js +1 -1
- package/dist/vue/components/ProviderMultiSelect.vue2.js +8 -5
- package/dist/vue/components/ProviderMultiSelect.vue2.js.map +1 -1
- package/dist/vue/components/ProviderSelect.vue.d.ts.map +1 -1
- package/dist/vue/components/ProviderSelect.vue.js +1 -1
- package/dist/vue/components/ProviderSelect.vue2.js +8 -5
- package/dist/vue/components/ProviderSelect.vue2.js.map +1 -1
- package/dist/vue/composables/useDerive.d.ts +1 -1
- package/dist/vue/composables/useDerive.d.ts.map +1 -1
- package/dist/vue/composables/useDerive.js +5 -1
- package/dist/vue/composables/useDerive.js.map +1 -1
- package/dist/vue/composables/useProjection.d.ts.map +1 -1
- package/dist/vue/composables/useProjection.js +1 -3
- package/dist/vue/composables/useProjection.js.map +1 -1
- package/dist/vue/index.d.ts.map +1 -1
- package/dist/vue/index.js +10 -2
- package/dist/vue/index.js.map +1 -1
- package/dist/vue/primevue/JfBoolean.vue.d.ts.map +1 -1
- package/dist/vue/primevue/JfBoolean.vue.js +14 -3
- package/dist/vue/primevue/JfBoolean.vue.js.map +1 -1
- package/dist/vue/primevue/JfEnum.vue.d.ts.map +1 -1
- package/dist/vue/primevue/JfEnum.vue.js +10 -5
- package/dist/vue/primevue/JfEnum.vue.js.map +1 -1
- package/dist/vue/primevue/JfEnumArray.vue.d.ts.map +1 -1
- package/dist/vue/primevue/JfEnumArray.vue.js +10 -5
- package/dist/vue/primevue/JfEnumArray.vue.js.map +1 -1
- package/dist/vue/primevue/JfNumber.vue.d.ts.map +1 -1
- package/dist/vue/primevue/JfNumber.vue.js +11 -6
- package/dist/vue/primevue/JfNumber.vue.js.map +1 -1
- package/dist/vue/primevue/JfText.vue.d.ts.map +1 -1
- package/dist/vue/primevue/JfText.vue.js +11 -6
- package/dist/vue/primevue/JfText.vue.js.map +1 -1
- package/dist/vue/primevue/JfTextArea.vue.d.ts.map +1 -1
- package/dist/vue/primevue/JfTextArea.vue.js +10 -5
- package/dist/vue/primevue/JfTextArea.vue.js.map +1 -1
- package/dist/vue/primevue/index.d.ts.map +1 -1
- package/dist/vue/primevue/index.js +93 -16
- package/dist/vue/primevue/index.js.map +1 -1
- package/dist/vue/utils/autoSelect.js.map +1 -1
- package/package.json +1 -1
- package/src/core/projection.ts +5 -5
- package/src/core/transforms.ts +33 -6
- package/src/vue/components/ProviderAutocomplete.vue +8 -5
- package/src/vue/components/ProviderMultiSelect.vue +12 -7
- package/src/vue/components/ProviderSelect.vue +9 -6
- package/src/vue/composables/useDerive.ts +16 -3
- package/src/vue/composables/useProjection.ts +6 -12
- package/src/vue/index.ts +10 -4
- package/src/vue/primevue/JfBoolean.vue +8 -3
- package/src/vue/primevue/JfEnum.vue +11 -8
- package/src/vue/primevue/JfEnumArray.vue +15 -12
- package/src/vue/primevue/JfNumber.vue +11 -8
- package/src/vue/primevue/JfText.vue +11 -8
- package/src/vue/primevue/JfTextArea.vue +10 -7
- package/src/vue/primevue/index.ts +104 -23
- package/src/vue/styles.css +26 -1
- package/src/vue/utils/autoSelect.ts +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projection.d.ts","sourceRoot":"","sources":["../../src/core/projection.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAC;AAEhD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAMrE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"projection.d.ts","sourceRoot":"","sources":["../../src/core/projection.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAC;AAEhD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAMrE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAiBtE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,GACb,OAAO,CAGT;AAqCD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAEhC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,IAAI,EAAE,MAAM,GAEX,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA8BrB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projection.js","sources":["../../src/core/projection.ts"],"sourcesContent":["/**\n * Projection utilities for navigating complex data structures\n * through a dot-separated path where numeric segments are array indices.\n *\n * Examples:\n * \"0\" → first element of an array\n * \"include\" → the `include` property of an object\n * \"0.video_rate_usd\" → nested property inside the first array element\n */\n\nexport type ProjectionSegment = string | number;\n\n/**\n * Parse a projection path string into typed segments.\n * Numeric strings become numbers (array indices), others stay as strings (object keys).\n */\nexport function parseProjectionPath(path: string): ProjectionSegment[] {\n if (!path) return [];\n return path.split(\".\").map((s) => {\n const n = Number(s);\n return Number.isInteger(n) && n >= 0 ? n : s;\n });\n}\n\n/**\n * Read a value from `data` by following the projection path.\n * Returns `undefined` if any segment along the path is missing.\n */\nexport function getProjectedValue(
|
|
1
|
+
{"version":3,"file":"projection.js","sources":["../../src/core/projection.ts"],"sourcesContent":["/**\n * Projection utilities for navigating complex data structures\n * through a dot-separated path where numeric segments are array indices.\n *\n * Examples:\n * \"0\" → first element of an array\n * \"include\" → the `include` property of an object\n * \"0.video_rate_usd\" → nested property inside the first array element\n */\n\nexport type ProjectionSegment = string | number;\n\n/**\n * Parse a projection path string into typed segments.\n * Numeric strings become numbers (array indices), others stay as strings (object keys).\n */\nexport function parseProjectionPath(path: string): ProjectionSegment[] {\n if (!path) return [];\n return path.split(\".\").map((s) => {\n const n = Number(s);\n return Number.isInteger(n) && n >= 0 ? n : s;\n });\n}\n\n/**\n * Read a value from `data` by following the projection path.\n * Returns `undefined` if any segment along the path is missing.\n */\nexport function getProjectedValue(data: unknown, path: string): unknown {\n const segments = parseProjectionPath(path);\n let current: unknown = data;\n\n for (const seg of segments) {\n if (current === null || current === undefined) return undefined;\n\n if (typeof seg === \"number\") {\n if (!Array.isArray(current)) return undefined;\n current = current[seg];\n } else {\n if (typeof current !== \"object\") return undefined;\n current = (current as Record<string, unknown>)[seg];\n }\n }\n\n return current;\n}\n\n/**\n * Immutably set a value at the projection path, preserving all sibling data.\n * Constructs missing intermediate structures (arrays for numeric segments, objects for string segments).\n */\nexport function setProjectedValue(\n data: unknown,\n path: string,\n value: unknown,\n): unknown {\n const segments = parseProjectionPath(path);\n return setAtPath(data, segments, 0, value);\n}\n\nfunction setAtPath(\n current: unknown,\n segments: ProjectionSegment[],\n index: number,\n value: unknown,\n): unknown {\n if (index === segments.length) {\n return value;\n }\n\n const seg = segments[index]!;\n\n if (typeof seg === \"number\") {\n // Array index — ensure we have an array\n const arr = Array.isArray(current) ? [...current] : [];\n // Pad array if index is out of bounds\n while (arr.length <= seg) {\n arr.push(undefined);\n }\n arr[seg] = setAtPath(arr[seg], segments, index + 1, value);\n return arr;\n } else {\n // Object key — ensure we have an object\n const obj: Record<string, unknown> =\n current !== null &&\n current !== undefined &&\n typeof current === \"object\" &&\n !Array.isArray(current)\n ? { ...(current as Record<string, unknown>) }\n : {};\n obj[seg] = setAtPath(obj[seg], segments, index + 1, value);\n return obj;\n }\n}\n\n/**\n * Resolve the schema at the projected path.\n * Numeric segments traverse into `items` (array item schema).\n * String segments traverse into `properties[segment]`.\n */\nexport function getProjectedSchema(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema: Record<string, any>,\n path: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): Record<string, any> {\n const segments = parseProjectionPath(path);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let current: Record<string, any> = schema;\n\n for (const seg of segments) {\n if (!current) return {};\n\n if (typeof seg === \"number\") {\n // Array index → traverse into items schema\n const items = current.items;\n if (items && typeof items === \"object\") {\n current = items as Record<string, unknown>;\n } else {\n return {};\n }\n } else {\n // Object key → traverse into properties[key]\n const properties = current.properties as\n | Record<string, Record<string, unknown>>\n | undefined;\n if (properties && properties[seg]) {\n current = properties[seg];\n } else {\n return {};\n }\n }\n }\n\n return current;\n}\n"],"names":[],"mappings":"AAgBO,SAAS,oBAAoB,MAAmC;AACrE,MAAI,CAAC,KAAM,QAAO,CAAA;AAClB,SAAO,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM;AAChC,UAAM,IAAI,OAAO,CAAC;AAClB,WAAO,OAAO,UAAU,CAAC,KAAK,KAAK,IAAI,IAAI;AAAA,EAC7C,CAAC;AACH;AAMO,SAAS,kBAAkB,MAAe,MAAuB;AACtE,QAAM,WAAW,oBAAoB,IAAI;AACzC,MAAI,UAAmB;AAEvB,aAAW,OAAO,UAAU;AAC1B,QAAI,YAAY,QAAQ,YAAY,OAAW,QAAO;AAEtD,QAAI,OAAO,QAAQ,UAAU;AAC3B,UAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,QAAO;AACpC,gBAAU,QAAQ,GAAG;AAAA,IACvB,OAAO;AACL,UAAI,OAAO,YAAY,SAAU,QAAO;AACxC,gBAAW,QAAoC,GAAG;AAAA,IACpD;AAAA,EACF;AAEA,SAAO;AACT;AAMO,SAAS,kBACd,MACA,MACA,OACS;AACT,QAAM,WAAW,oBAAoB,IAAI;AACzC,SAAO,UAAU,MAAM,UAAU,GAAG,KAAK;AAC3C;AAEA,SAAS,UACP,SACA,UACA,OACA,OACS;AACT,MAAI,UAAU,SAAS,QAAQ;AAC7B,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,SAAS,KAAK;AAE1B,MAAI,OAAO,QAAQ,UAAU;AAE3B,UAAM,MAAM,MAAM,QAAQ,OAAO,IAAI,CAAC,GAAG,OAAO,IAAI,CAAA;AAEpD,WAAO,IAAI,UAAU,KAAK;AACxB,UAAI,KAAK,MAAS;AAAA,IACpB;AACA,QAAI,GAAG,IAAI,UAAU,IAAI,GAAG,GAAG,UAAU,QAAQ,GAAG,KAAK;AACzD,WAAO;AAAA,EACT,OAAO;AAEL,UAAM,MACJ,YAAY,QACZ,YAAY,UACZ,OAAO,YAAY,YACnB,CAAC,MAAM,QAAQ,OAAO,IAClB,EAAE,GAAI,QAAA,IACN,CAAA;AACN,QAAI,GAAG,IAAI,UAAU,IAAI,GAAG,GAAG,UAAU,QAAQ,GAAG,KAAK;AACzD,WAAO;AAAA,EACT;AACF;AAOO,SAAS,mBAEd,QACA,MAEqB;AACrB,QAAM,WAAW,oBAAoB,IAAI;AAEzC,MAAI,UAA+B;AAEnC,aAAW,OAAO,UAAU;AAC1B,QAAI,CAAC,QAAS,QAAO,CAAA;AAErB,QAAI,OAAO,QAAQ,UAAU;AAE3B,YAAM,QAAQ,QAAQ;AACtB,UAAI,SAAS,OAAO,UAAU,UAAU;AACtC,kBAAU;AAAA,MACZ,OAAO;AACL,eAAO,CAAA;AAAA,MACT;AAAA,IACF,OAAO;AAEL,YAAM,aAAa,QAAQ;AAG3B,UAAI,cAAc,WAAW,GAAG,GAAG;AACjC,kBAAU,WAAW,GAAG;AAAA,MAC1B,OAAO;AACL,eAAO,CAAA;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transforms.d.ts","sourceRoot":"","sources":["../../src/core/transforms.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IACjD,IAAI,EAAE,SAAS,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"transforms.d.ts","sourceRoot":"","sources":["../../src/core/transforms.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IACjD,IAAI,EAAE,SAAS,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,cAAc,GACtB,IAAI,GACJ,KAAK,GACL,OAAO,GACP,UAAU,GACV,IAAI,GACJ,KAAK,GACL,IAAI,GACJ,KAAK,GACL,UAAU,CAAC;AAEf,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAChD,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;CAChC;AAED,MAAM,MAAM,aAAa,GAAG,gBAAgB,GAAG,eAAe,CAAC;AAE/D,MAAM,MAAM,iBAAiB,GAAG,aAAa,EAAE,CAAC;AAMhD;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EAAE,EAChB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,EAAE,CAYX"}
|
package/dist/core/transforms.js
CHANGED
|
@@ -113,7 +113,9 @@ function filterTransform(items, config) {
|
|
|
113
113
|
return items.filter((item) => {
|
|
114
114
|
if (typeof item !== "object" || item === null) return false;
|
|
115
115
|
const itemObj = item;
|
|
116
|
-
return conditions.every(
|
|
116
|
+
return conditions.every(
|
|
117
|
+
(condition) => evaluateCondition(itemObj, condition)
|
|
118
|
+
);
|
|
117
119
|
});
|
|
118
120
|
}
|
|
119
121
|
transformRegistry["flatten"] = flattenTransform;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transforms.js","sources":["../../src/core/transforms.ts"],"sourcesContent":["/**\n * Transform pipeline system for manipulating API response data\n * Transforms are applied sequentially in the order they appear in the pipeline\n */\n\nexport interface Transform {\n name: string;\n [key: string]: unknown;\n}\n\nexport interface FlattenTransform extends Transform {\n name: \"flatten\";\n key: string; // The key containing the nested array to flatten\n labelFormat?: string; // Optional format string like \"{parent.name} → {name}\"\n}\n\nexport type FilterOperator = \"eq\" | \"neq\" | \"empty\" | \"notEmpty\" | \"gt\" | \"gte\" | \"lt\" | \"lte\" | \"contains\";\n\nexport interface FilterCondition {\n key: string;\n operator?: FilterOperator; // Defaults to \"eq\" when values is provided, \"exists\" behavior when neither\n values?: unknown[];\n}\n\nexport interface FilterTransform extends Transform {\n name: \"filter\";\n key?: string; // Legacy: single key to check\n values?: unknown[]; // Legacy: single values array\n conditions?: FilterCondition[]; // Multi-condition filter (AND logic)\n}\n\nexport type TransformStep = FlattenTransform | FilterTransform;\n\nexport type TransformPipeline = TransformStep[];\n\ntype TransformFunction = (items: unknown[], config: Transform) => unknown[];\n\nconst transformRegistry: Record<string, TransformFunction> = {};\n\n/**\n * Apply a pipeline of transforms to data\n */\nexport function applyTransformPipeline(\n items: unknown[],\n pipeline: TransformPipeline,\n): unknown[] {\n let result = items;\n\n for (const transform of pipeline) {\n const fn = transformRegistry[transform.name];\n if (!fn) {\n throw new Error(`Unknown transform: ${transform.name}`);\n }\n result = fn(result, transform);\n }\n\n return result;\n}\n\n/**\n * Flatten transform - recursively flattens nested arrays into a single level\n */\nfunction flattenTransform(items: unknown[], config: Transform): unknown[] {\n const flattenConfig = config as FlattenTransform;\n const { key, labelFormat } = flattenConfig;\n const flattened: unknown[] = [];\n\n function flattenRecursive(\n item: unknown,\n parent: Record<string, unknown> | null = null,\n depth: number = 0,\n ): void {\n if (typeof item !== \"object\" || item === null) return;\n\n const itemObj = item as Record<string, unknown>;\n\n // Add the current item\n if (labelFormat && parent) {\n const formattedItem = { ...itemObj };\n\n // Replace placeholders like {parent.name} and {name}\n let formattedLabel = labelFormat;\n formattedLabel = formattedLabel.replace(/\\{parent\\.(\\w+)\\}/g, (_, prop) =>\n String(parent[prop] ?? \"\"),\n );\n formattedLabel = formattedLabel.replace(/\\{(\\w+)\\}/g, (_, prop) =>\n String(itemObj[prop] ?? \"\"),\n );\n\n formattedItem._formattedLabel = formattedLabel;\n formattedItem._parent = parent;\n formattedItem._depth = depth;\n flattened.push(formattedItem);\n } else if (parent) {\n // Child node with parent reference\n flattened.push({\n ...itemObj,\n _parent: parent,\n _depth: depth,\n });\n } else {\n // Root node\n flattened.push({\n ...itemObj,\n _depth: depth,\n });\n }\n\n // Recursively flatten children\n const children = itemObj[key];\n if (Array.isArray(children)) {\n for (const child of children) {\n flattenRecursive(child, itemObj, depth + 1);\n }\n }\n }\n\n // Start flattening from root items\n for (const item of items) {\n flattenRecursive(item, null, 0);\n }\n\n return flattened;\n}\n\nfunction isEmpty(value: unknown): boolean {\n if (value === null || value === undefined) return true;\n if (Array.isArray(value)) return value.length === 0;\n if (typeof value === \"string\") return value.length === 0;\n return false;\n}\n\nfunction evaluateCondition(\n itemObj: Record<string, unknown>,\n condition: FilterCondition,\n): boolean {\n const value = itemObj[condition.key];\n const operator = condition.operator ?? (condition.values ? \"eq\" : \"eq\");\n\n switch (operator) {\n case \"eq\":\n if (!condition.values || condition.values.length === 0) {\n return condition.key in itemObj;\n }\n return condition.values.includes(value);\n case \"neq\":\n if (!condition.values || condition.values.length === 0) {\n return !(condition.key in itemObj);\n }\n return !condition.values.includes(value);\n case \"empty\":\n return isEmpty(value);\n case \"notEmpty\":\n return !isEmpty(value);\n case \"gt\":\n return typeof value === \"number\" && condition.values !== undefined && value > (condition.values[0] as number);\n case \"gte\":\n return typeof value === \"number\" && condition.values !== undefined && value >= (condition.values[0] as number);\n case \"lt\":\n return typeof value === \"number\" && condition.values !== undefined && value < (condition.values[0] as number);\n case \"lte\":\n return typeof value === \"number\" && condition.values !== undefined && value <= (condition.values[0] as number);\n case \"contains\":\n if (typeof value === \"string\" && condition.values) {\n return condition.values.some((v) => value.includes(String(v)));\n }\n if (Array.isArray(value) && condition.values) {\n return condition.values.some((v) => value.includes(v));\n }\n return false;\n default:\n return false;\n }\n}\n\n/**\n * Filter transform - filters items based on conditions\n *\n * Supports legacy single key/values syntax and new multi-condition syntax.\n * When using conditions, all conditions must match (AND logic).\n *\n * Operators:\n * eq - item[key] matches one of values (default)\n * neq - item[key] does NOT match any of values\n * empty - item[key] is null, undefined, empty array, or empty string\n * notEmpty - inverse of empty\n * gt - item[key] > values[0]\n * gte - item[key] >= values[0]\n * lt - item[key] < values[0]\n * lte - item[key] <= values[0]\n * contains - string includes substring, or array includes value\n */\nfunction filterTransform(items: unknown[], config: Transform): unknown[] {\n const filterConfig = config as FilterTransform;\n\n // Build conditions array from either new or legacy syntax\n let conditions: FilterCondition[];\n\n if (filterConfig.conditions) {\n conditions = filterConfig.conditions;\n } else if (filterConfig.key) {\n // Legacy single key/values syntax\n conditions = [{ key: filterConfig.key, values: filterConfig.values }];\n } else {\n return items;\n }\n\n return items.filter((item) => {\n if (typeof item !== \"object\" || item === null) return false;\n const itemObj = item as Record<string, unknown>;\n return conditions.every((condition) => evaluateCondition(itemObj, condition));\n });\n}\n\n// Register built-in transforms\ntransformRegistry[\"flatten\"] = flattenTransform;\ntransformRegistry[\"filter\"] = filterTransform;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transforms.js","sources":["../../src/core/transforms.ts"],"sourcesContent":["/**\n * Transform pipeline system for manipulating API response data\n * Transforms are applied sequentially in the order they appear in the pipeline\n */\n\nexport interface Transform {\n name: string;\n [key: string]: unknown;\n}\n\nexport interface FlattenTransform extends Transform {\n name: \"flatten\";\n key: string; // The key containing the nested array to flatten\n labelFormat?: string; // Optional format string like \"{parent.name} → {name}\"\n}\n\nexport type FilterOperator =\n | \"eq\"\n | \"neq\"\n | \"empty\"\n | \"notEmpty\"\n | \"gt\"\n | \"gte\"\n | \"lt\"\n | \"lte\"\n | \"contains\";\n\nexport interface FilterCondition {\n key: string;\n operator?: FilterOperator; // Defaults to \"eq\" when values is provided, \"exists\" behavior when neither\n values?: unknown[];\n}\n\nexport interface FilterTransform extends Transform {\n name: \"filter\";\n key?: string; // Legacy: single key to check\n values?: unknown[]; // Legacy: single values array\n conditions?: FilterCondition[]; // Multi-condition filter (AND logic)\n}\n\nexport type TransformStep = FlattenTransform | FilterTransform;\n\nexport type TransformPipeline = TransformStep[];\n\ntype TransformFunction = (items: unknown[], config: Transform) => unknown[];\n\nconst transformRegistry: Record<string, TransformFunction> = {};\n\n/**\n * Apply a pipeline of transforms to data\n */\nexport function applyTransformPipeline(\n items: unknown[],\n pipeline: TransformPipeline,\n): unknown[] {\n let result = items;\n\n for (const transform of pipeline) {\n const fn = transformRegistry[transform.name];\n if (!fn) {\n throw new Error(`Unknown transform: ${transform.name}`);\n }\n result = fn(result, transform);\n }\n\n return result;\n}\n\n/**\n * Flatten transform - recursively flattens nested arrays into a single level\n */\nfunction flattenTransform(items: unknown[], config: Transform): unknown[] {\n const flattenConfig = config as FlattenTransform;\n const { key, labelFormat } = flattenConfig;\n const flattened: unknown[] = [];\n\n function flattenRecursive(\n item: unknown,\n parent: Record<string, unknown> | null = null,\n depth: number = 0,\n ): void {\n if (typeof item !== \"object\" || item === null) return;\n\n const itemObj = item as Record<string, unknown>;\n\n // Add the current item\n if (labelFormat && parent) {\n const formattedItem = { ...itemObj };\n\n // Replace placeholders like {parent.name} and {name}\n let formattedLabel = labelFormat;\n formattedLabel = formattedLabel.replace(/\\{parent\\.(\\w+)\\}/g, (_, prop) =>\n String(parent[prop] ?? \"\"),\n );\n formattedLabel = formattedLabel.replace(/\\{(\\w+)\\}/g, (_, prop) =>\n String(itemObj[prop] ?? \"\"),\n );\n\n formattedItem._formattedLabel = formattedLabel;\n formattedItem._parent = parent;\n formattedItem._depth = depth;\n flattened.push(formattedItem);\n } else if (parent) {\n // Child node with parent reference\n flattened.push({\n ...itemObj,\n _parent: parent,\n _depth: depth,\n });\n } else {\n // Root node\n flattened.push({\n ...itemObj,\n _depth: depth,\n });\n }\n\n // Recursively flatten children\n const children = itemObj[key];\n if (Array.isArray(children)) {\n for (const child of children) {\n flattenRecursive(child, itemObj, depth + 1);\n }\n }\n }\n\n // Start flattening from root items\n for (const item of items) {\n flattenRecursive(item, null, 0);\n }\n\n return flattened;\n}\n\nfunction isEmpty(value: unknown): boolean {\n if (value === null || value === undefined) return true;\n if (Array.isArray(value)) return value.length === 0;\n if (typeof value === \"string\") return value.length === 0;\n return false;\n}\n\nfunction evaluateCondition(\n itemObj: Record<string, unknown>,\n condition: FilterCondition,\n): boolean {\n const value = itemObj[condition.key];\n const operator = condition.operator ?? (condition.values ? \"eq\" : \"eq\");\n\n switch (operator) {\n case \"eq\":\n if (!condition.values || condition.values.length === 0) {\n return condition.key in itemObj;\n }\n return condition.values.includes(value);\n case \"neq\":\n if (!condition.values || condition.values.length === 0) {\n return !(condition.key in itemObj);\n }\n return !condition.values.includes(value);\n case \"empty\":\n return isEmpty(value);\n case \"notEmpty\":\n return !isEmpty(value);\n case \"gt\":\n return (\n typeof value === \"number\" &&\n condition.values !== undefined &&\n value > (condition.values[0] as number)\n );\n case \"gte\":\n return (\n typeof value === \"number\" &&\n condition.values !== undefined &&\n value >= (condition.values[0] as number)\n );\n case \"lt\":\n return (\n typeof value === \"number\" &&\n condition.values !== undefined &&\n value < (condition.values[0] as number)\n );\n case \"lte\":\n return (\n typeof value === \"number\" &&\n condition.values !== undefined &&\n value <= (condition.values[0] as number)\n );\n case \"contains\":\n if (typeof value === \"string\" && condition.values) {\n return condition.values.some((v) => value.includes(String(v)));\n }\n if (Array.isArray(value) && condition.values) {\n return condition.values.some((v) => value.includes(v));\n }\n return false;\n default:\n return false;\n }\n}\n\n/**\n * Filter transform - filters items based on conditions\n *\n * Supports legacy single key/values syntax and new multi-condition syntax.\n * When using conditions, all conditions must match (AND logic).\n *\n * Operators:\n * eq - item[key] matches one of values (default)\n * neq - item[key] does NOT match any of values\n * empty - item[key] is null, undefined, empty array, or empty string\n * notEmpty - inverse of empty\n * gt - item[key] > values[0]\n * gte - item[key] >= values[0]\n * lt - item[key] < values[0]\n * lte - item[key] <= values[0]\n * contains - string includes substring, or array includes value\n */\nfunction filterTransform(items: unknown[], config: Transform): unknown[] {\n const filterConfig = config as FilterTransform;\n\n // Build conditions array from either new or legacy syntax\n let conditions: FilterCondition[];\n\n if (filterConfig.conditions) {\n conditions = filterConfig.conditions;\n } else if (filterConfig.key) {\n // Legacy single key/values syntax\n conditions = [{ key: filterConfig.key, values: filterConfig.values }];\n } else {\n return items;\n }\n\n return items.filter((item) => {\n if (typeof item !== \"object\" || item === null) return false;\n const itemObj = item as Record<string, unknown>;\n return conditions.every((condition) =>\n evaluateCondition(itemObj, condition),\n );\n });\n}\n\n// Register built-in transforms\ntransformRegistry[\"flatten\"] = flattenTransform;\ntransformRegistry[\"filter\"] = filterTransform;\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProviderAutocomplete.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/ProviderAutocomplete.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProviderAutocomplete.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/ProviderAutocomplete.vue"],"names":[],"mappings":"AAgFA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAOlE,KAAK,WAAW,GAAG;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;;AA2JF,wBAEG"}
|
|
@@ -3,14 +3,14 @@ import { useJsonFormsControl } from "@jsonforms/vue";
|
|
|
3
3
|
import { useProvider } from "../composables/useProvider.js";
|
|
4
4
|
import { useProjection } from "../composables/useProjection.js";
|
|
5
5
|
import AutoComplete from "primevue/autocomplete";
|
|
6
|
-
const _hoisted_1 = { class: "
|
|
6
|
+
const _hoisted_1 = { class: "jf-control" };
|
|
7
7
|
const _hoisted_2 = {
|
|
8
8
|
key: 0,
|
|
9
|
-
class: "
|
|
9
|
+
class: "jf-label"
|
|
10
10
|
};
|
|
11
11
|
const _hoisted_3 = {
|
|
12
12
|
key: 1,
|
|
13
|
-
class: "
|
|
13
|
+
class: "jf-description"
|
|
14
14
|
};
|
|
15
15
|
const _hoisted_4 = {
|
|
16
16
|
key: 2,
|
|
@@ -27,7 +27,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
27
27
|
setup(__props) {
|
|
28
28
|
const props = __props;
|
|
29
29
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
30
|
-
const { projectedData, handleProjectedChange: handleChange } = useProjection(
|
|
30
|
+
const { projectedData, handleProjectedChange: handleChange } = useProjection(
|
|
31
|
+
control,
|
|
32
|
+
rawHandleChange
|
|
33
|
+
);
|
|
31
34
|
const binding = computed(() => {
|
|
32
35
|
const provider = control.value.uischema?.options?.provider;
|
|
33
36
|
if (provider && typeof provider === "object" && !provider.load) {
|
|
@@ -64,7 +67,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
64
67
|
createVNode(unref(AutoComplete), {
|
|
65
68
|
modelValue: value.value,
|
|
66
69
|
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => value.value = $event),
|
|
67
|
-
class: "w-full",
|
|
70
|
+
class: "w-full!",
|
|
68
71
|
suggestions: unref(items),
|
|
69
72
|
"option-label": "label",
|
|
70
73
|
placeholder: placeholder.value,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProviderAutocomplete.vue.js","sources":["../../../src/vue/components/ProviderAutocomplete.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ControlElement, JsonSchema } from \"@jsonforms/core\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, ref, watch } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\nimport { useProjection } from \"../composables/useProjection\";\nimport AutoComplete from \"primevue/autocomplete\";\n\nconst props = defineProps<{\n uischema: ControlElement;\n schema: JsonSchema;\n path: string;\n}>();\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange } = useProjection(control
|
|
1
|
+
{"version":3,"file":"ProviderAutocomplete.vue.js","sources":["../../../src/vue/components/ProviderAutocomplete.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ControlElement, JsonSchema } from \"@jsonforms/core\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, ref, watch } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\nimport { useProjection } from \"../composables/useProjection\";\nimport AutoComplete from \"primevue/autocomplete\";\n\nconst props = defineProps<{\n uischema: ControlElement;\n schema: JsonSchema;\n path: string;\n}>();\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange } = useProjection(\n control,\n rawHandleChange,\n);\n\nconst binding = computed(() => {\n const provider = control.value.uischema?.options?.provider;\n // Ensure load property is set to 'query' by default for autocomplete\n if (provider && typeof provider === \"object\" && !provider.load) {\n return { ...provider, load: \"query\" };\n }\n return provider;\n});\n\nconst query = ref(\"\");\nconst { items, loading, error, reload } = useProvider(binding, {\n data: control.value.data,\n path: control.value.path,\n uiQuery: query.value,\n});\n\nwatch(query, () => {\n if (binding.value?.load === \"query\") reload();\n});\n\nconst value = computed({\n get: () => projectedData.value,\n set: (v) => handleChange(control.value.path, v),\n});\n\nconst placeholder = computed(() =>\n loading.value ? \"Loading…\" : \"Type to search…\",\n);\n\nconst onComplete = (event: { query: string }) => {\n query.value = event.query;\n};\n\nconst onSelect = (event: { value?: { value?: unknown } | unknown }) => {\n value.value = (event.value as { value?: unknown })?.value ?? event.value;\n};\n</script>\n\n<template>\n <div class=\"jf-control\">\n <label v-if=\"control.schema.title\" class=\"jf-label\">{{\n control.schema.title\n }}</label>\n <div v-if=\"control.description\" class=\"jf-description\">\n {{ control.description }}\n </div>\n <AutoComplete\n v-model=\"value\"\n class=\"w-full!\"\n :suggestions=\"items\"\n option-label=\"label\"\n :placeholder=\"placeholder\"\n :disabled=\"!control.enabled\"\n @complete=\"onComplete\"\n @item-select=\"onSelect\"\n />\n <small v-if=\"error\" class=\"p-error\" role=\"alert\">Failed: {{ error }}</small>\n </div>\n</template>\n"],"names":["_openBlock","_createElementBlock","_unref","_toDisplayString","_createVNode"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,UAAM,QAAQ;AAKd,UAAM,EAAE,SAAS,cAAc,gBAAA,IAAoB,oBAAoB,KAAK;AAC5E,UAAM,EAAE,eAAe,uBAAuB,aAAA,IAAiB;AAAA,MAC7D;AAAA,MACA;AAAA,IAAA;AAGF,UAAM,UAAU,SAAS,MAAM;AAC7B,YAAM,WAAW,QAAQ,MAAM,UAAU,SAAS;AAElD,UAAI,YAAY,OAAO,aAAa,YAAY,CAAC,SAAS,MAAM;AAC9D,eAAO,EAAE,GAAG,UAAU,MAAM,QAAA;AAAA,MAC9B;AACA,aAAO;AAAA,IACT,CAAC;AAED,UAAM,QAAQ,IAAI,EAAE;AACpB,UAAM,EAAE,OAAO,SAAS,OAAO,OAAA,IAAW,YAAY,SAAS;AAAA,MAC7D,MAAM,QAAQ,MAAM;AAAA,MACpB,MAAM,QAAQ,MAAM;AAAA,MACpB,SAAS,MAAM;AAAA,IAAA,CAChB;AAED,UAAM,OAAO,MAAM;AACjB,UAAI,QAAQ,OAAO,SAAS,QAAS,QAAA;AAAA,IACvC,CAAC;AAED,UAAM,QAAQ,SAAS;AAAA,MACrB,KAAK,MAAM,cAAc;AAAA,MACzB,KAAK,CAAC,MAAM,aAAa,QAAQ,MAAM,MAAM,CAAC;AAAA,IAAA,CAC/C;AAED,UAAM,cAAc;AAAA,MAAS,MAC3B,QAAQ,QAAQ,aAAa;AAAA,IAAA;AAG/B,UAAM,aAAa,CAAC,UAA6B;AAC/C,YAAM,QAAQ,MAAM;AAAA,IACtB;AAEA,UAAM,WAAW,CAAC,UAAqD;AACrE,YAAM,QAAS,MAAM,OAA+B,SAAS,MAAM;AAAA,IACrE;;AAIE,aAAAA,UAAA,GAAAC,mBAkBM,OAlBN,YAkBM;AAAA,QAjBSC,MAAA,OAAA,EAAQ,OAAO,SAA5BF,aAAAC,mBAEU,SAFV,YAEUE,gBADRD,eAAQ,OAAO,KAAK,GAAA,CAAA;QAEXA,MAAA,OAAA,EAAQ,eAAnBF,UAAA,GAAAC,mBAEM,OAFN,YAEME,gBADDD,MAAA,OAAA,EAAQ,WAAW,GAAA,CAAA;QAExBE,YASEF,MAAA,YAAA,GAAA;AAAA,sBARS,MAAA;AAAA,uEAAA,MAAK,QAAA;AAAA,UACd,OAAM;AAAA,UACL,aAAaA,MAAA,KAAA;AAAA,UACd,gBAAa;AAAA,UACZ,aAAa,YAAA;AAAA,UACb,UAAQ,CAAGA,MAAA,OAAA,EAAQ;AAAA,UACnB;AAAA,UACA,cAAa;AAAA,QAAA;QAEHA,MAAA,KAAA,KAAbF,aAAAC,mBAA4E,SAA5E,YAAiD,6BAAWC,MAAA,KAAA,CAAK,GAAA,CAAA;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProviderMultiSelect.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/ProviderMultiSelect.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProviderMultiSelect.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/ProviderMultiSelect.vue"],"names":[],"mappings":"AAyIA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAQlE,KAAK,WAAW,GAAG;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;;AAuMF,wBAEG"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _sfc_main from "./ProviderMultiSelect.vue2.js";
|
|
2
2
|
/* empty css */
|
|
3
3
|
import _export_sfc from "../../_virtual/_plugin-vue_export-helper.js";
|
|
4
|
-
const ProviderMultiSelect = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
4
|
+
const ProviderMultiSelect = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-679ae32b"]]);
|
|
5
5
|
export {
|
|
6
6
|
ProviderMultiSelect as default
|
|
7
7
|
};
|
|
@@ -4,14 +4,14 @@ import { useProvider } from "../composables/useProvider.js";
|
|
|
4
4
|
import { useProjection } from "../composables/useProjection.js";
|
|
5
5
|
import { shouldAutoSelectMulti } from "../utils/autoSelect.js";
|
|
6
6
|
import MultiSelect from "primevue/multiselect";
|
|
7
|
-
const _hoisted_1 = { class: "
|
|
7
|
+
const _hoisted_1 = { class: "jf-control" };
|
|
8
8
|
const _hoisted_2 = {
|
|
9
9
|
key: 0,
|
|
10
|
-
class: "
|
|
10
|
+
class: "jf-label"
|
|
11
11
|
};
|
|
12
12
|
const _hoisted_3 = {
|
|
13
13
|
key: 1,
|
|
14
|
-
class: "
|
|
14
|
+
class: "jf-description"
|
|
15
15
|
};
|
|
16
16
|
const _hoisted_4 = {
|
|
17
17
|
key: 2,
|
|
@@ -28,7 +28,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
28
28
|
setup(__props) {
|
|
29
29
|
const props = __props;
|
|
30
30
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
31
|
-
const { projectedData, handleProjectedChange: handleChange } = useProjection(
|
|
31
|
+
const { projectedData, handleProjectedChange: handleChange } = useProjection(
|
|
32
|
+
control,
|
|
33
|
+
rawHandleChange
|
|
34
|
+
);
|
|
32
35
|
const binding = computed(() => {
|
|
33
36
|
const provider = control.value.uischema?.options?.provider;
|
|
34
37
|
if (provider && typeof provider === "object" && !provider.load) {
|
|
@@ -92,7 +95,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
92
95
|
createVNode(unref(MultiSelect), {
|
|
93
96
|
modelValue: value.value,
|
|
94
97
|
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => value.value = $event),
|
|
95
|
-
class: "w-full",
|
|
98
|
+
class: "w-full!",
|
|
96
99
|
options: unref(items),
|
|
97
100
|
"option-label": "label",
|
|
98
101
|
"option-value": "value",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProviderMultiSelect.vue2.js","sources":["../../../src/vue/components/ProviderMultiSelect.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ControlElement, JsonSchema } from \"@jsonforms/core\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, inject, watch } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { shouldAutoSelectMulti } from \"../utils/autoSelect\";\nimport MultiSelect from \"primevue/multiselect\";\n\nconst props = defineProps<{\n uischema: ControlElement;\n schema: JsonSchema;\n path: string;\n}>();\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange } = useProjection(control
|
|
1
|
+
{"version":3,"file":"ProviderMultiSelect.vue2.js","sources":["../../../src/vue/components/ProviderMultiSelect.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ControlElement, JsonSchema } from \"@jsonforms/core\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, inject, watch } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { shouldAutoSelectMulti } from \"../utils/autoSelect\";\nimport MultiSelect from \"primevue/multiselect\";\n\nconst props = defineProps<{\n uischema: ControlElement;\n schema: JsonSchema;\n path: string;\n}>();\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange } = useProjection(\n control,\n rawHandleChange,\n);\n\nconst binding = computed(() => {\n const provider = control.value.uischema?.options?.provider;\n // Ensure load property is set to 'mount' by default\n if (provider && typeof provider === \"object\" && !provider.load) {\n return { ...provider, load: \"mount\" };\n }\n return provider;\n});\n\nconst deps = computed(\n () =>\n ((\n (control.value.schema as Record<string, unknown>)?.[\n \"x-provider\"\n ] as Record<string, unknown>\n )?.dependsOn as string[]) ?? [],\n);\nconst depValues = computed(() => deps.value.map(() => null)); // you can resolve actual values via control.value.data & pointers\n\n// Get the root form data from JSONForms context for template URL resolution\nconst injectedFormData = inject<{ value: unknown }>(\"formData\", { value: {} });\nconst rootData = computed(() => injectedFormData.value || {});\n\nconst { items, loading, error } = useProvider(binding, {\n data: rootData, // Pass the reactive reference\n path: control.value.path,\n dependsOnValues: depValues.value,\n});\n\n// Provider will automatically reload when rootData changes due to reactive cache key\n\n// Auto-select when provider returns only one item (opt-in for multiselect)\nwatch(\n [items, loading],\n ([newItems, isLoading]) => {\n const valueToSelect = shouldAutoSelectMulti({\n autoSelectSingle:\n control.value.uischema?.options?.autoSelectSingle === true,\n isLoading,\n items: newItems,\n currentValue: Array.isArray(projectedData.value)\n ? projectedData.value\n : [],\n });\n\n if (valueToSelect !== null) {\n handleChange(control.value.path, valueToSelect);\n }\n },\n { immediate: true },\n);\n\n// order-insensitive shallow equality for primitive arrays\nconst sameSet = (a: unknown[], b: unknown[]) => {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length)\n return false;\n const s = new Set(b);\n return a.every((v) => s.has(v));\n};\n\n// v-model with guard to avoid recursive updates\nconst value = computed({\n get() {\n const curr = Array.isArray(projectedData.value) ? projectedData.value : [];\n // return a fresh copy so MultiSelect can't mutate JSONForms' array in place\n return [...curr];\n },\n set(val) {\n const next = Array.isArray(val) ? [...val] : [];\n const curr = Array.isArray(projectedData.value) ? projectedData.value : [];\n if (!sameSet(curr, next)) handleChange(control.value.path, next);\n },\n});\n\nconst placeholder = computed(() => {\n if (loading.value) return \"Loading…\";\n // Check for placeholder in uischema options\n const uischemaPlaceholder = (\n control.value.uischema as { options?: { placeholder?: string } }\n )?.options?.placeholder;\n return uischemaPlaceholder || \"Select…\";\n});\n</script>\n\n<template>\n <div class=\"jf-control\">\n <label v-if=\"control.schema.title\" class=\"jf-label\">{{\n control.schema.title\n }}</label>\n <div v-if=\"control.description\" class=\"jf-description\">\n {{ control.description }}\n </div>\n <MultiSelect\n v-model=\"value\"\n class=\"w-full!\"\n :options=\"items\"\n option-label=\"label\"\n option-value=\"value\"\n data-key=\"value\"\n display=\"chip\"\n :placeholder=\"placeholder\"\n :disabled=\"!control.enabled || loading\"\n :show-clear=\"true\"\n />\n <small v-if=\"error\" class=\"p-error\" role=\"alert\"\n >Failed to load: {{ error }}</small\n >\n </div>\n</template>\n\n<style scoped>\n:deep(.p-multiselect-label) {\n text-align: left;\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_unref","_toDisplayString","_createVNode"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProviderSelect.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/ProviderSelect.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProviderSelect.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/ProviderSelect.vue"],"names":[],"mappings":"AAoHA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAQlE,KAAK,WAAW,GAAG;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;;AAgLF,wBAEG"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _sfc_main from "./ProviderSelect.vue2.js";
|
|
2
2
|
/* empty css */
|
|
3
3
|
import _export_sfc from "../../_virtual/_plugin-vue_export-helper.js";
|
|
4
|
-
const ProviderSelect = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
4
|
+
const ProviderSelect = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-140d349a"]]);
|
|
5
5
|
export {
|
|
6
6
|
ProviderSelect as default
|
|
7
7
|
};
|
|
@@ -4,14 +4,14 @@ import { useProvider } from "../composables/useProvider.js";
|
|
|
4
4
|
import { useProjection } from "../composables/useProjection.js";
|
|
5
5
|
import { shouldAutoSelect } from "../utils/autoSelect.js";
|
|
6
6
|
import Dropdown from "primevue/dropdown";
|
|
7
|
-
const _hoisted_1 = { class: "
|
|
7
|
+
const _hoisted_1 = { class: "jf-control" };
|
|
8
8
|
const _hoisted_2 = {
|
|
9
9
|
key: 0,
|
|
10
|
-
class: "
|
|
10
|
+
class: "jf-label"
|
|
11
11
|
};
|
|
12
12
|
const _hoisted_3 = {
|
|
13
13
|
key: 1,
|
|
14
|
-
class: "
|
|
14
|
+
class: "jf-description"
|
|
15
15
|
};
|
|
16
16
|
const _hoisted_4 = {
|
|
17
17
|
key: 2,
|
|
@@ -28,7 +28,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
28
28
|
setup(__props) {
|
|
29
29
|
const props = __props;
|
|
30
30
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
31
|
-
const { projectedData, handleProjectedChange: handleChange } = useProjection(
|
|
31
|
+
const { projectedData, handleProjectedChange: handleChange } = useProjection(
|
|
32
|
+
control,
|
|
33
|
+
rawHandleChange
|
|
34
|
+
);
|
|
32
35
|
const binding = computed(() => {
|
|
33
36
|
const provider = control.value.uischema?.options?.provider;
|
|
34
37
|
if (provider && typeof provider === "object" && !provider.load) {
|
|
@@ -79,7 +82,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
79
82
|
createVNode(unref(Dropdown), {
|
|
80
83
|
modelValue: value.value,
|
|
81
84
|
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => value.value = $event),
|
|
82
|
-
class: "w-full",
|
|
85
|
+
class: "w-full!",
|
|
83
86
|
options: unref(items),
|
|
84
87
|
"option-label": "label",
|
|
85
88
|
"option-value": "value",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProviderSelect.vue2.js","sources":["../../../src/vue/components/ProviderSelect.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ControlElement, JsonSchema } from \"@jsonforms/core\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, inject, watch } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { shouldAutoSelect } from \"../utils/autoSelect\";\nimport Dropdown from \"primevue/dropdown\";\n\nconst props = defineProps<{\n uischema: ControlElement;\n schema: JsonSchema;\n path: string;\n}>();\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange } = useProjection(control
|
|
1
|
+
{"version":3,"file":"ProviderSelect.vue2.js","sources":["../../../src/vue/components/ProviderSelect.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ControlElement, JsonSchema } from \"@jsonforms/core\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, inject, watch } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { shouldAutoSelect } from \"../utils/autoSelect\";\nimport Dropdown from \"primevue/dropdown\";\n\nconst props = defineProps<{\n uischema: ControlElement;\n schema: JsonSchema;\n path: string;\n}>();\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange } = useProjection(\n control,\n rawHandleChange,\n);\n\nconst binding = computed(() => {\n const provider = control.value.uischema?.options?.provider;\n // Ensure load property is set to 'mount' by default\n if (provider && typeof provider === \"object\" && !provider.load) {\n return { ...provider, load: \"mount\" };\n }\n return provider;\n});\n\nconst deps = computed(\n () =>\n ((\n (control.value.schema as Record<string, unknown>)?.[\n \"x-provider\"\n ] as Record<string, unknown>\n )?.dependsOn as string[]) ?? [],\n);\nconst depValues = computed(() => deps.value.map(() => null)); // you can resolve actual values via control.value.data & pointers\n\n// Get the root form data from JSONForms context for template URL resolution\nconst injectedFormData = inject<{ value: unknown }>(\"formData\", { value: {} });\nconst rootData = computed(() => injectedFormData.value || {});\n\nconst { items, loading, error } = useProvider(binding, {\n data: rootData, // Pass the reactive reference\n path: control.value.path,\n dependsOnValues: depValues.value,\n});\n\n// Provider will automatically reload when rootData changes due to reactive cache key\n\n// Auto-select when provider returns only one item (enabled by default)\nwatch(\n [items, loading],\n ([newItems, isLoading]) => {\n const valueToSelect = shouldAutoSelect({\n autoSelectSingle:\n control.value.uischema?.options?.autoSelectSingle !== false,\n isLoading,\n items: newItems,\n currentValue: projectedData.value,\n });\n\n if (valueToSelect !== null) {\n handleChange(control.value.path, valueToSelect);\n }\n },\n { immediate: true },\n);\n\nconst value = computed({\n get: () => projectedData.value,\n set: (v) => handleChange(control.value.path, v),\n});\n\nconst placeholder = computed(() => {\n if (loading.value) return \"Loading…\";\n // Check for placeholder in uischema options\n const uischemaPlaceholder = (\n control.value.uischema as { options?: { placeholder?: string } }\n )?.options?.placeholder;\n return uischemaPlaceholder || \"Select…\";\n});\n</script>\n\n<template>\n <div class=\"jf-control\">\n <label v-if=\"control.schema.title\" class=\"jf-label\">{{\n control.schema.title\n }}</label>\n <div v-if=\"control.description\" class=\"jf-description\">\n {{ control.description }}\n </div>\n <Dropdown\n v-model=\"value\"\n class=\"w-full!\"\n :options=\"items\"\n option-label=\"label\"\n option-value=\"value\"\n :placeholder=\"placeholder\"\n :disabled=\"!control.enabled || loading\"\n :show-clear=\"true\"\n />\n <small v-if=\"error\" class=\"p-error\" role=\"alert\"\n >Failed to load: {{ error }}</small\n >\n </div>\n</template>\n\n<style scoped>\n:deep(.p-dropdown-label) {\n text-align: left;\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_unref","_toDisplayString","_createVNode"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA,UAAM,QAAQ;AAKd,UAAM,EAAE,SAAS,cAAc,gBAAA,IAAoB,oBAAoB,KAAK;AAC5E,UAAM,EAAE,eAAe,uBAAuB,aAAA,IAAiB;AAAA,MAC7D;AAAA,MACA;AAAA,IAAA;AAGF,UAAM,UAAU,SAAS,MAAM;AAC7B,YAAM,WAAW,QAAQ,MAAM,UAAU,SAAS;AAElD,UAAI,YAAY,OAAO,aAAa,YAAY,CAAC,SAAS,MAAM;AAC9D,eAAO,EAAE,GAAG,UAAU,MAAM,QAAA;AAAA,MAC9B;AACA,aAAO;AAAA,IACT,CAAC;AAED,UAAM,OAAO;AAAA,MACX,MAEK,QAAQ,MAAM,SACb,YACF,GACC,aAA0B,CAAA;AAAA,IAAC;AAElC,UAAM,YAAY,SAAS,MAAM,KAAK,MAAM,IAAI,MAAM,IAAI,CAAC;AAG3D,UAAM,mBAAmB,OAA2B,YAAY,EAAE,OAAO,CAAA,GAAI;AAC7E,UAAM,WAAW,SAAS,MAAM,iBAAiB,SAAS,CAAA,CAAE;AAE5D,UAAM,EAAE,OAAO,SAAS,MAAA,IAAU,YAAY,SAAS;AAAA,MACrD,MAAM;AAAA;AAAA,MACN,MAAM,QAAQ,MAAM;AAAA,MACpB,iBAAiB,UAAU;AAAA,IAAA,CAC5B;AAKD;AAAA,MACE,CAAC,OAAO,OAAO;AAAA,MACf,CAAC,CAAC,UAAU,SAAS,MAAM;AACzB,cAAM,gBAAgB,iBAAiB;AAAA,UACrC,kBACE,QAAQ,MAAM,UAAU,SAAS,qBAAqB;AAAA,UACxD;AAAA,UACA,OAAO;AAAA,UACP,cAAc,cAAc;AAAA,QAAA,CAC7B;AAED,YAAI,kBAAkB,MAAM;AAC1B,uBAAa,QAAQ,MAAM,MAAM,aAAa;AAAA,QAChD;AAAA,MACF;AAAA,MACA,EAAE,WAAW,KAAA;AAAA,IAAK;AAGpB,UAAM,QAAQ,SAAS;AAAA,MACrB,KAAK,MAAM,cAAc;AAAA,MACzB,KAAK,CAAC,MAAM,aAAa,QAAQ,MAAM,MAAM,CAAC;AAAA,IAAA,CAC/C;AAED,UAAM,cAAc,SAAS,MAAM;AACjC,UAAI,QAAQ,MAAO,QAAO;AAE1B,YAAM,sBACJ,QAAQ,MAAM,UACb,SAAS;AACZ,aAAO,uBAAuB;AAAA,IAChC,CAAC;;AAIC,aAAAA,UAAA,GAAAC,mBAoBM,OApBN,YAoBM;AAAA,QAnBSC,MAAA,OAAA,EAAQ,OAAO,SAA5BF,aAAAC,mBAEU,SAFV,YAEUE,gBADRD,eAAQ,OAAO,KAAK,GAAA,CAAA;QAEXA,MAAA,OAAA,EAAQ,eAAnBF,UAAA,GAAAC,mBAEM,OAFN,YAEME,gBADDD,MAAA,OAAA,EAAQ,WAAW,GAAA,CAAA;QAExBE,YASEF,MAAA,QAAA,GAAA;AAAA,sBARS,MAAA;AAAA,uEAAA,MAAK,QAAA;AAAA,UACd,OAAM;AAAA,UACL,SAASA,MAAA,KAAA;AAAA,UACV,gBAAa;AAAA,UACb,gBAAa;AAAA,UACZ,aAAa,YAAA;AAAA,UACb,UAAQ,CAAGA,MAAA,OAAA,EAAQ,WAAWA,MAAA,OAAA;AAAA,UAC9B,cAAY;AAAA,QAAA;QAEFA,MAAA,KAAA,KAAbF,aAAAC,mBAEC,SAFD,YACG,qCAAmBC,MAAA,KAAA,CAAK,GAAA,CAAA;;;;;"}
|
|
@@ -11,6 +11,6 @@ interface DeriveOptions {
|
|
|
11
11
|
* matches the projected (unwrapped) value rather than raw scope data. */
|
|
12
12
|
data?: Ref<unknown> | ComputedRef<unknown>;
|
|
13
13
|
}
|
|
14
|
-
export declare function useDerive({ control, handleChange, data: dataOverride }: DeriveOptions): void;
|
|
14
|
+
export declare function useDerive({ control, handleChange, data: dataOverride, }: DeriveOptions): void;
|
|
15
15
|
export {};
|
|
16
16
|
//# sourceMappingURL=useDerive.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDerive.d.ts","sourceRoot":"","sources":["../../../src/vue/composables/useDerive.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"useDerive.d.ts","sourceRoot":"","sources":["../../../src/vue/composables/useDerive.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,GAAG,EACR,KAAK,WAAW,EACjB,MAAM,KAAK,CAAC;AACb,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGtD,UAAU,aAAa;IACrB,OAAO,EAAE,GAAG,CAAC;QACX,QAAQ,EAAE,cAAc,CAAC;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,OAAO,CAAC;KACf,CAAC,CAAC;IACH,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD;8EAC0E;IAC1E,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;CAC5C;AAED,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,YAAY,EACZ,IAAI,EAAE,YAAY,GACnB,EAAE,aAAa,QAmDf"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { inject, computed, watch, unref } from "vue";
|
|
2
2
|
import "@jsonforms/core";
|
|
3
3
|
import { useDataLayer } from "./useDataLayer.js";
|
|
4
|
-
function useDerive({
|
|
4
|
+
function useDerive({
|
|
5
|
+
control,
|
|
6
|
+
handleChange,
|
|
7
|
+
data: dataOverride
|
|
8
|
+
}) {
|
|
5
9
|
const injectedFormData = inject("formData", {
|
|
6
10
|
value: {}
|
|
7
11
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDerive.js","sources":["../../../src/vue/composables/useDerive.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"useDerive.js","sources":["../../../src/vue/composables/useDerive.ts"],"sourcesContent":["import {\n computed,\n watch,\n unref,\n inject,\n type Ref,\n type ComputedRef,\n} from \"vue\";\nimport { type ControlElement } from \"@jsonforms/core\";\nimport { useDataLayer } from \"./useDataLayer\";\n\ninterface DeriveOptions {\n control: Ref<{\n uischema: ControlElement;\n path: string;\n data: unknown;\n }>;\n handleChange: (path: string, value: unknown) => void;\n /** When projection is active, pass projectedData so the comparison\n * matches the projected (unwrapped) value rather than raw scope data. */\n data?: Ref<unknown> | ComputedRef<unknown>;\n}\n\nexport function useDerive({\n control,\n handleChange,\n data: dataOverride,\n}: DeriveOptions) {\n // Get the root form data from JSONForms context\n const injectedFormData = inject<{ value: unknown }>(\"formData\", {\n value: {},\n });\n const rootData = computed(() => injectedFormData.value || {});\n\n // Get data from the dataLayer\n const dataLayerState = useDataLayer();\n const dataLayerData = computed(() => dataLayerState.value || {});\n\n // Extract derive configuration from uischema options\n const deriveConfig = computed(() => {\n const options = control.value.uischema?.options as\n | { derive?: string; mode?: string }\n | undefined;\n return {\n expression: options?.derive,\n mode: options?.mode || \"follow\", // 'follow' = auto-update, 'manual' = user controlled\n };\n });\n\n // Watch for changes in form data and dataLayer and update derived field\n watch(\n [rootData, dataLayerData, deriveConfig],\n ([data, extData, config]) => {\n if (!config.expression || config.mode !== \"follow\") {\n return;\n }\n\n try {\n const derivedValue = resolveDeriveExpression(\n config.expression,\n data,\n extData,\n );\n const compareData = dataOverride\n ? unref(dataOverride)\n : control.value.data;\n if (derivedValue !== compareData) {\n handleChange(control.value.path, derivedValue);\n }\n } catch (error) {\n console.warn(\n `Failed to derive value for ${control.value.path}:`,\n error,\n );\n }\n },\n { deep: true, immediate: true },\n );\n}\n\nfunction resolveDeriveExpression(\n expression: string,\n data: unknown,\n dataLayerData?: unknown,\n): unknown {\n // Handle dataLayer() syntax\n if (expression.startsWith(\"dataLayer(\") && expression.endsWith(\")\")) {\n const propertyPath = expression.slice(10, -1); // Remove \"dataLayer(\" and \")\"\n return resolvePropertyPath(propertyPath, dataLayerData);\n }\n\n // Handle simple property paths like \"country.name\"\n if (\n !expression.includes(\"(\") &&\n !expression.includes(\"+\") &&\n !expression.includes(\"?\")\n ) {\n return resolvePropertyPath(expression, data);\n }\n\n // For now, we'll only support simple property paths and dataLayer() calls\n // Complex expressions would require a safe expression evaluator\n return resolvePropertyPath(expression, data);\n}\n\nfunction resolvePropertyPath(path: string, data: unknown): unknown {\n if (!path || !data) return \"\";\n\n const keys = path.split(\".\");\n let value: unknown = data;\n\n for (const key of keys) {\n if (value && typeof value === \"object\" && key in value) {\n value = (value as Record<string, unknown>)[key];\n } else {\n return null;\n }\n }\n\n return value;\n}\n"],"names":[],"mappings":";;;AAuBO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,MAAM;AACR,GAAkB;AAEhB,QAAM,mBAAmB,OAA2B,YAAY;AAAA,IAC9D,OAAO,CAAA;AAAA,EAAC,CACT;AACD,QAAM,WAAW,SAAS,MAAM,iBAAiB,SAAS,CAAA,CAAE;AAG5D,QAAM,iBAAiB,aAAA;AACvB,QAAM,gBAAgB,SAAS,MAAM,eAAe,SAAS,CAAA,CAAE;AAG/D,QAAM,eAAe,SAAS,MAAM;AAClC,UAAM,UAAU,QAAQ,MAAM,UAAU;AAGxC,WAAO;AAAA,MACL,YAAY,SAAS;AAAA,MACrB,MAAM,SAAS,QAAQ;AAAA;AAAA,IAAA;AAAA,EAE3B,CAAC;AAGD;AAAA,IACE,CAAC,UAAU,eAAe,YAAY;AAAA,IACtC,CAAC,CAAC,MAAM,SAAS,MAAM,MAAM;AAC3B,UAAI,CAAC,OAAO,cAAc,OAAO,SAAS,UAAU;AAClD;AAAA,MACF;AAEA,UAAI;AACF,cAAM,eAAe;AAAA,UACnB,OAAO;AAAA,UACP;AAAA,UACA;AAAA,QAAA;AAEF,cAAM,cAAc,eAChB,MAAM,YAAY,IAClB,QAAQ,MAAM;AAClB,YAAI,iBAAiB,aAAa;AAChC,uBAAa,QAAQ,MAAM,MAAM,YAAY;AAAA,QAC/C;AAAA,MACF,SAAS,OAAO;AACd,gBAAQ;AAAA,UACN,8BAA8B,QAAQ,MAAM,IAAI;AAAA,UAChD;AAAA,QAAA;AAAA,MAEJ;AAAA,IACF;AAAA,IACA,EAAE,MAAM,MAAM,WAAW,KAAA;AAAA,EAAK;AAElC;AAEA,SAAS,wBACP,YACA,MACA,eACS;AAET,MAAI,WAAW,WAAW,YAAY,KAAK,WAAW,SAAS,GAAG,GAAG;AACnE,UAAM,eAAe,WAAW,MAAM,IAAI,EAAE;AAC5C,WAAO,oBAAoB,cAAc,aAAa;AAAA,EACxD;AAGA,MACE,CAAC,WAAW,SAAS,GAAG,KACxB,CAAC,WAAW,SAAS,GAAG,KACxB,CAAC,WAAW,SAAS,GAAG,GACxB;AACA,WAAO,oBAAoB,YAAY,IAAI;AAAA,EAC7C;AAIA,SAAO,oBAAoB,YAAY,IAAI;AAC7C;AAEA,SAAS,oBAAoB,MAAc,MAAwB;AACjE,MAAI,CAAC,QAAQ,CAAC,KAAM,QAAO;AAE3B,QAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,MAAI,QAAiB;AAErB,aAAW,OAAO,MAAM;AACtB,QAAI,SAAS,OAAO,UAAU,YAAY,OAAO,OAAO;AACtD,cAAS,MAAkC,GAAG;AAAA,IAChD,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useProjection.d.ts","sourceRoot":"","sources":["../../../src/vue/composables/useProjection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,WAAW,EAAE,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAOnE,UAAU,iBAAiB;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,QAAQ,EAAE;QAAE,OAAO,CAAC,EAAE;YAAE,UAAU,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;SAAE,CAAA;KAAE,CAAC;CACzE;
|
|
1
|
+
{"version":3,"file":"useProjection.d.ts","sourceRoot":"","sources":["../../../src/vue/composables/useProjection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,WAAW,EAAE,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAOnE,UAAU,iBAAiB;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,QAAQ,EAAE;QAAE,OAAO,CAAC,EAAE;YAAE,UAAU,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;SAAE,CAAA;KAAE,CAAC;CACzE;AAyDD,MAAM,WAAW,gBAAgB;IAC/B,sDAAsD;IACtD,aAAa,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IACpC,gEAAgE;IAEhE,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAClD,8DAA8D;IAC9D,qBAAqB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9D,mCAAmC;IACnC,aAAa,EAAE,OAAO,CAAC;IACvB,sFAAsF;IACtF,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACpC,qEAAqE;IACrE,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACtC;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,GAAG,CAAC,iBAAiB,CAAC,EAC/B,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,GACnD,gBAAgB,CA+ElB"}
|
|
@@ -60,9 +60,7 @@ function useProjection(control, handleChange) {
|
|
|
60
60
|
if (matching.length === 0) {
|
|
61
61
|
errStr = baseErrors;
|
|
62
62
|
} else {
|
|
63
|
-
const projMsg = matching.map(
|
|
64
|
-
(e) => e.keyword === "required" ? "is required" : e.message
|
|
65
|
-
).filter(Boolean).join("\n");
|
|
63
|
+
const projMsg = matching.map((e) => e.keyword === "required" ? "is required" : e.message).filter(Boolean).join("\n");
|
|
66
64
|
errStr = [baseErrors, projMsg].filter(Boolean).join("\n");
|
|
67
65
|
}
|
|
68
66
|
return prefixErrors(label.value.replace(/\*$/, "").trim(), errStr);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useProjection.js","sources":["../../../src/vue/composables/useProjection.ts"],"sourcesContent":["import { computed, inject, type ComputedRef, type Ref } from \"vue\";\nimport {\n getProjectedValue,\n setProjectedValue,\n getProjectedSchema,\n} from \"../../core/projection\";\n\ninterface ProjectionControl {\n data: unknown;\n path: string;\n errors: string;\n label?: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema: Record<string, any>;\n uischema: { options?: { projection?: string; [key: string]: unknown } };\n}\n\n// Minimal AJV ErrorObject shape for filtering\ninterface ErrorLike {\n instancePath?: string;\n keyword?: string;\n message?: string;\n params?: { missingProperty?: string };\n}\n\n/**\n * Resolve the display label for a control.\n * Priority: uischema options.label → schemaTitle (projected sub-schema) → control.label.\n */\nfunction resolveLabel(
|
|
1
|
+
{"version":3,"file":"useProjection.js","sources":["../../../src/vue/composables/useProjection.ts"],"sourcesContent":["import { computed, inject, type ComputedRef, type Ref } from \"vue\";\nimport {\n getProjectedValue,\n setProjectedValue,\n getProjectedSchema,\n} from \"../../core/projection\";\n\ninterface ProjectionControl {\n data: unknown;\n path: string;\n errors: string;\n label?: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema: Record<string, any>;\n uischema: { options?: { projection?: string; [key: string]: unknown } };\n}\n\n// Minimal AJV ErrorObject shape for filtering\ninterface ErrorLike {\n instancePath?: string;\n keyword?: string;\n message?: string;\n params?: { missingProperty?: string };\n}\n\n/**\n * Resolve the display label for a control.\n * Priority: uischema options.label → schemaTitle (projected sub-schema) → control.label.\n */\nfunction resolveLabel(ctrl: ProjectionControl, schemaTitle?: string): string {\n return (\n (ctrl.uischema?.options?.label as string) ?? schemaTitle ?? ctrl.label ?? \"\"\n );\n}\n\n/**\n * Normalize AJV error message fragments into user-friendly text.\n * e.g. \"is a required property\" → \"is required\"\n */\nfunction normalizeErrors(errors: string): string {\n if (!errors) return errors;\n return errors\n .replace(/is a required property/g, \"is required\")\n .replace(/must have required property '[^']*'/g, \"is required\");\n}\n\n/**\n * Prefix each error message line with the field label so that AJV fragments\n * like \"is required\" become \"Name is required\".\n */\nfunction prefixErrors(label: string, errors: string): string {\n if (!label || !errors) return errors;\n return errors\n .split(\"\\n\")\n .map((line) => `${label} ${line}`)\n .join(\"\\n\");\n}\n\n/**\n * Convert an AJV ErrorObject's instancePath to a dot-separated control path.\n * Replicates the logic from @jsonforms/core getControlPath.\n */\nfunction getErrorPath(error: ErrorLike): string {\n let p = (error.instancePath || \"\").replace(/\\//g, \".\").replace(/^\\./, \"\");\n if (error.keyword === \"required\" && error.params?.missingProperty) {\n p = p\n ? p + \".\" + error.params.missingProperty\n : error.params.missingProperty;\n }\n return p;\n}\n\nexport interface ProjectionResult {\n /** The value at the projected path (for rendering) */\n projectedData: ComputedRef<unknown>;\n /** The schema at the projected path (for renderer selection) */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n projectedSchema: ComputedRef<Record<string, any>>;\n /** Wrapped handleChange that writes through the projection */\n handleProjectedChange: (path: string, value: unknown) => void;\n /** Whether projection is active */\n hasProjection: boolean;\n /** Resolved display label (options.label → projected schema title → control.label) */\n projectedLabel: ComputedRef<string>;\n /** Error string combining base-path and projected sub-path errors */\n projectedErrors: ComputedRef<string>;\n}\n\n/**\n * Composable that wraps a JSON Forms control with projection support.\n *\n * When `options.projection` is set on the uischema, this composable:\n * - Reads the projected sub-value from the control data\n * - Resolves the projected sub-schema for renderer type resolution\n * - Wraps handleChange to write back through the projection path (preserving siblings)\n *\n * When no projection is set, it passes through control data/schema/handleChange unchanged.\n */\nexport function useProjection(\n control: Ref<ProjectionControl>,\n handleChange: (path: string, value: unknown) => void,\n): ProjectionResult {\n const projection = control.value.uischema?.options?.projection as\n | string\n | undefined;\n\n if (!projection) {\n const label = computed(() => resolveLabel(control.value));\n return {\n projectedData: computed(() => control.value.data),\n projectedSchema: computed(() => control.value.schema),\n handleProjectedChange: handleChange,\n hasProjection: false,\n projectedLabel: label,\n projectedErrors: computed(() =>\n prefixErrors(\n label.value.replace(/\\*$/, \"\").trim(),\n normalizeErrors(control.value.errors),\n ),\n ),\n };\n }\n\n // Inject JSONForms state to access raw AJV errors for projected sub-paths.\n // control.errors only contains errors at the exact control path (e.g. \"data_rates\"),\n // but projected fields need errors at the full path (e.g. \"data_rates.0.video_rate_usd\").\n const jsonforms = inject<{ core?: { errors?: ErrorLike[] } } | null>(\n \"jsonforms\",\n null,\n );\n\n const fullProjectedPath = control.value.path + \".\" + projection;\n\n const projectedData = computed(() =>\n getProjectedValue(control.value.data, projection),\n );\n\n const projectedSchema = computed(() =>\n getProjectedSchema(control.value.schema, projection),\n );\n\n const label = computed(() =>\n resolveLabel(control.value, projectedSchema.value?.title),\n );\n\n const projectedErrors = computed(() => {\n const baseErrors = normalizeErrors(control.value.errors || \"\");\n\n const rawErrors = jsonforms?.core?.errors ?? [];\n const matching = rawErrors.filter(\n (err) => getErrorPath(err) === fullProjectedPath,\n );\n\n let errStr: string;\n if (matching.length === 0) {\n errStr = baseErrors;\n } else {\n const projMsg = matching\n .map((e) => (e.keyword === \"required\" ? \"is required\" : e.message))\n .filter(Boolean)\n .join(\"\\n\");\n errStr = [baseErrors, projMsg].filter(Boolean).join(\"\\n\");\n }\n\n return prefixErrors(label.value.replace(/\\*$/, \"\").trim(), errStr);\n });\n\n const handleProjectedChange = (path: string, value: unknown) => {\n const fullValue = setProjectedValue(control.value.data, projection, value);\n handleChange(path, fullValue);\n };\n\n return {\n projectedData,\n projectedSchema,\n handleProjectedChange,\n hasProjection: true,\n projectedLabel: label,\n projectedErrors,\n };\n}\n"],"names":["label"],"mappings":";;AA6BA,SAAS,aAAa,MAAyB,aAA8B;AAC3E,SACG,KAAK,UAAU,SAAS,SAAoB,eAAe,KAAK,SAAS;AAE9E;AAMA,SAAS,gBAAgB,QAAwB;AAC/C,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OACJ,QAAQ,2BAA2B,aAAa,EAChD,QAAQ,wCAAwC,aAAa;AAClE;AAMA,SAAS,aAAa,OAAe,QAAwB;AAC3D,MAAI,CAAC,SAAS,CAAC,OAAQ,QAAO;AAC9B,SAAO,OACJ,MAAM,IAAI,EACV,IAAI,CAAC,SAAS,GAAG,KAAK,IAAI,IAAI,EAAE,EAChC,KAAK,IAAI;AACd;AAMA,SAAS,aAAa,OAA0B;AAC9C,MAAI,KAAK,MAAM,gBAAgB,IAAI,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,EAAE;AACxE,MAAI,MAAM,YAAY,cAAc,MAAM,QAAQ,iBAAiB;AACjE,QAAI,IACA,IAAI,MAAM,MAAM,OAAO,kBACvB,MAAM,OAAO;AAAA,EACnB;AACA,SAAO;AACT;AA4BO,SAAS,cACd,SACA,cACkB;AAClB,QAAM,aAAa,QAAQ,MAAM,UAAU,SAAS;AAIpD,MAAI,CAAC,YAAY;AACf,UAAMA,SAAQ,SAAS,MAAM,aAAa,QAAQ,KAAK,CAAC;AACxD,WAAO;AAAA,MACL,eAAe,SAAS,MAAM,QAAQ,MAAM,IAAI;AAAA,MAChD,iBAAiB,SAAS,MAAM,QAAQ,MAAM,MAAM;AAAA,MACpD,uBAAuB;AAAA,MACvB,eAAe;AAAA,MACf,gBAAgBA;AAAAA,MAChB,iBAAiB;AAAA,QAAS,MACxB;AAAA,UACEA,OAAM,MAAM,QAAQ,OAAO,EAAE,EAAE,KAAA;AAAA,UAC/B,gBAAgB,QAAQ,MAAM,MAAM;AAAA,QAAA;AAAA,MACtC;AAAA,IACF;AAAA,EAEJ;AAKA,QAAM,YAAY;AAAA,IAChB;AAAA,IACA;AAAA,EAAA;AAGF,QAAM,oBAAoB,QAAQ,MAAM,OAAO,MAAM;AAErD,QAAM,gBAAgB;AAAA,IAAS,MAC7B,kBAAkB,QAAQ,MAAM,MAAM,UAAU;AAAA,EAAA;AAGlD,QAAM,kBAAkB;AAAA,IAAS,MAC/B,mBAAmB,QAAQ,MAAM,QAAQ,UAAU;AAAA,EAAA;AAGrD,QAAM,QAAQ;AAAA,IAAS,MACrB,aAAa,QAAQ,OAAO,gBAAgB,OAAO,KAAK;AAAA,EAAA;AAG1D,QAAM,kBAAkB,SAAS,MAAM;AACrC,UAAM,aAAa,gBAAgB,QAAQ,MAAM,UAAU,EAAE;AAE7D,UAAM,YAAY,WAAW,MAAM,UAAU,CAAA;AAC7C,UAAM,WAAW,UAAU;AAAA,MACzB,CAAC,QAAQ,aAAa,GAAG,MAAM;AAAA,IAAA;AAGjC,QAAI;AACJ,QAAI,SAAS,WAAW,GAAG;AACzB,eAAS;AAAA,IACX,OAAO;AACL,YAAM,UAAU,SACb,IAAI,CAAC,MAAO,EAAE,YAAY,aAAa,gBAAgB,EAAE,OAAQ,EACjE,OAAO,OAAO,EACd,KAAK,IAAI;AACZ,eAAS,CAAC,YAAY,OAAO,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAAA,IAC1D;AAEA,WAAO,aAAa,MAAM,MAAM,QAAQ,OAAO,EAAE,EAAE,KAAA,GAAQ,MAAM;AAAA,EACnE,CAAC;AAED,QAAM,wBAAwB,CAAC,MAAc,UAAmB;AAC9D,UAAM,YAAY,kBAAkB,QAAQ,MAAM,MAAM,YAAY,KAAK;AACzE,iBAAa,MAAM,SAAS;AAAA,EAC9B;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB;AAAA,EAAA;AAEJ;"}
|
package/dist/vue/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vue/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAUvD,OAAO,oBAAoB,MAAM,uCAAuC,CAAC;AACzE,OAAO,cAAc,MAAM,iCAAiC,CAAC;AAC7D,OAAO,mBAAmB,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vue/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAUvD,OAAO,oBAAoB,MAAM,uCAAuC,CAAC;AACzE,OAAO,cAAc,MAAM,iCAAiC,CAAC;AAC7D,OAAO,mBAAmB,MAAM,sCAAsC,CAAC;AA2DvE,eAAO,MAAM,iBAAiB;;;;;;;;;;;GAI7B,CAAC;AAGF,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAG1E,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,mBAAmB,EAAE,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,YAAY,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC3E,YAAY,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,cAAc,WAAW,CAAC;AAG1B,OAAO,EACL,MAAM,EACN,UAAU,EACV,QAAQ,EACR,MAAM,EACN,WAAW,EACX,SAAS,GACV,MAAM,YAAY,CAAC"}
|
package/dist/vue/index.js
CHANGED
|
@@ -21,7 +21,11 @@ const hasProvider = (uischema) => {
|
|
|
21
21
|
const isIntegerScope = (uischema, schema) => {
|
|
22
22
|
const ui = uischema;
|
|
23
23
|
if (ui?.type !== "Control" || !ui?.scope) return false;
|
|
24
|
-
const propertySchema = resolveScopeSchema(
|
|
24
|
+
const propertySchema = resolveScopeSchema(
|
|
25
|
+
ui.scope,
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
schema
|
|
28
|
+
);
|
|
25
29
|
return propertySchema?.type === "integer";
|
|
26
30
|
};
|
|
27
31
|
const providerSelectTester = rankWith(
|
|
@@ -47,7 +51,11 @@ const isArrayControl = (uischema, schema) => {
|
|
|
47
51
|
if (controlSchema.type !== "Control" || !controlSchema.scope) {
|
|
48
52
|
return false;
|
|
49
53
|
}
|
|
50
|
-
const propertySchema = resolveScopeSchema(
|
|
54
|
+
const propertySchema = resolveScopeSchema(
|
|
55
|
+
controlSchema.scope,
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
57
|
+
schema
|
|
58
|
+
);
|
|
51
59
|
return propertySchema?.type === "array";
|
|
52
60
|
};
|
|
53
61
|
const providerMultiSelectTester = rankWith(
|
package/dist/vue/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/vue/index.ts"],"sourcesContent":["import type { UISchemaElement } from \"@jsonforms/core\";\nimport {\n and,\n isNumberControl,\n isStringControl,\n or,\n rankWith,\n isControl,\n} from \"@jsonforms/core\";\nimport { resolveScopeSchema } from \"../core/resolveScope\";\nimport ProviderAutocomplete from \"./components/ProviderAutocomplete.vue\";\nimport ProviderSelect from \"./components/ProviderSelect.vue\";\nimport ProviderMultiSelect from \"./components/ProviderMultiSelect.vue\";\n\n// Custom tester that checks if provider option exists (as object or boolean)\nconst hasProvider = (uischema: UISchemaElement) => {\n return uischema?.options?.provider !== undefined;\n};\n\n// Integer fallback tester — handles nested scopes like #/properties/parent/properties/child\nconst isIntegerScope = (uischema: unknown, schema: unknown) => {\n const ui = uischema as { type?: string; scope?: string };\n if (ui?.type !== \"Control\" || !ui?.scope) return false;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/vue/index.ts"],"sourcesContent":["import type { UISchemaElement } from \"@jsonforms/core\";\nimport {\n and,\n isNumberControl,\n isStringControl,\n or,\n rankWith,\n isControl,\n} from \"@jsonforms/core\";\nimport { resolveScopeSchema } from \"../core/resolveScope\";\nimport ProviderAutocomplete from \"./components/ProviderAutocomplete.vue\";\nimport ProviderSelect from \"./components/ProviderSelect.vue\";\nimport ProviderMultiSelect from \"./components/ProviderMultiSelect.vue\";\n\n// Custom tester that checks if provider option exists (as object or boolean)\nconst hasProvider = (uischema: UISchemaElement) => {\n return uischema?.options?.provider !== undefined;\n};\n\n// Integer fallback tester — handles nested scopes like #/properties/parent/properties/child\nconst isIntegerScope = (uischema: unknown, schema: unknown) => {\n const ui = uischema as { type?: string; scope?: string };\n if (ui?.type !== \"Control\" || !ui?.scope) return false;\n\n const propertySchema = resolveScopeSchema(\n ui.scope,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema as Record<string, any>,\n );\n return propertySchema?.type === \"integer\";\n};\n\n// Create specific testers for each component type\nconst providerSelectTester = rankWith(\n 106, // Higher than PrimeVue base (100) to ensure providers take precedence\n and(\n or(isStringControl, isNumberControl, and(isControl, isIntegerScope)),\n hasProvider,\n (uischema) => !uischema?.options?.autocomplete,\n ),\n);\n\nconst providerAutocompleteTester = rankWith(\n 107, // Higher than PrimeVue base (100) to ensure providers take precedence\n and(\n or(isStringControl, isNumberControl, and(isControl, isIntegerScope)),\n hasProvider,\n (uischema) => uischema?.options?.autocomplete === true,\n ),\n);\n\n// Custom array tester - supports nested scope paths\nconst isArrayControl = (uischema: UISchemaElement, schema: unknown) => {\n const controlSchema = uischema as { type: string; scope?: string };\n if (controlSchema.type !== \"Control\" || !controlSchema.scope) {\n return false;\n }\n\n const propertySchema = resolveScopeSchema(\n controlSchema.scope,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema as Record<string, any>,\n );\n return propertySchema?.type === \"array\";\n};\n\nconst providerMultiSelectTester = rankWith(\n 108, // Highest priority for array controls with providers\n and(isArrayControl, hasProvider),\n);\n\nexport const providerRenderers = [\n { tester: providerMultiSelectTester, renderer: ProviderMultiSelect },\n { tester: providerAutocompleteTester, renderer: ProviderAutocomplete },\n { tester: providerSelectTester, renderer: ProviderSelect },\n];\n\n// Export PrimeVue renderers (styles are auto-injected)\nexport { primevueRenderers, registerPrimevueRenderers } from \"./primevue\";\n\n// Export individual components\nexport { ProviderAutocomplete, ProviderSelect, ProviderMultiSelect };\nexport { useProvider } from \"./composables/useProvider\";\nexport { useProjection } from \"./composables/useProjection\";\nexport type { ProjectionResult } from \"./composables/useProjection\";\nexport { createDataLayer, useDataLayer } from \"./composables/useDataLayer\";\nexport type { DataLayer } from \"./composables/useDataLayer\";\nexport { useDirtyValidation } from \"./composables/useDirtyValidation\";\nexport * from \"./testers\";\n\n// Export individual PrimeVue components using lazy evaluation to avoid circular deps\nexport {\n JfText,\n JfTextArea,\n JfNumber,\n JfEnum,\n JfEnumArray,\n JfBoolean,\n} from \"./primevue\";\n"],"names":["ProviderAutocomplete"],"mappings":";;;;;;;;;;;;;;;;;AAeA,MAAM,cAAc,CAAC,aAA8B;AACjD,SAAO,UAAU,SAAS,aAAa;AACzC;AAGA,MAAM,iBAAiB,CAAC,UAAmB,WAAoB;AAC7D,QAAM,KAAK;AACX,MAAI,IAAI,SAAS,aAAa,CAAC,IAAI,MAAO,QAAO;AAEjD,QAAM,iBAAiB;AAAA,IACrB,GAAG;AAAA;AAAA,IAEH;AAAA,EAAA;AAEF,SAAO,gBAAgB,SAAS;AAClC;AAGA,MAAM,uBAAuB;AAAA,EAC3B;AAAA;AAAA,EACA;AAAA,IACE,GAAG,iBAAiB,iBAAiB,IAAI,WAAW,cAAc,CAAC;AAAA,IACnE;AAAA,IACA,CAAC,aAAa,CAAC,UAAU,SAAS;AAAA,EAAA;AAEtC;AAEA,MAAM,6BAA6B;AAAA,EACjC;AAAA;AAAA,EACA;AAAA,IACE,GAAG,iBAAiB,iBAAiB,IAAI,WAAW,cAAc,CAAC;AAAA,IACnE;AAAA,IACA,CAAC,aAAa,UAAU,SAAS,iBAAiB;AAAA,EAAA;AAEtD;AAGA,MAAM,iBAAiB,CAAC,UAA2B,WAAoB;AACrE,QAAM,gBAAgB;AACtB,MAAI,cAAc,SAAS,aAAa,CAAC,cAAc,OAAO;AAC5D,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB;AAAA,IACrB,cAAc;AAAA;AAAA,IAEd;AAAA,EAAA;AAEF,SAAO,gBAAgB,SAAS;AAClC;AAEA,MAAM,4BAA4B;AAAA,EAChC;AAAA;AAAA,EACA,IAAI,gBAAgB,WAAW;AACjC;AAEO,MAAM,oBAAoB;AAAA,EAC/B,EAAE,QAAQ,2BAA2B,UAAU,oBAAA;AAAA,EAC/C,EAAE,QAAQ,4BAA4B,UAAUA,UAAA;AAAA,EAChD,EAAE,QAAQ,sBAAsB,UAAU,eAAA;AAC5C;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JfBoolean.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfBoolean.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"JfBoolean.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfBoolean.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2FA,wBAoLK"}
|