@dataverse-kit/form-runtime 0.1.0

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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/dist/businessRules-U1_MBgyG.d.cts +372 -0
  4. package/dist/businessRules-U1_MBgyG.d.ts +372 -0
  5. package/dist/context.cjs +151 -0
  6. package/dist/context.cjs.map +1 -0
  7. package/dist/context.d.cts +132 -0
  8. package/dist/context.d.ts +132 -0
  9. package/dist/context.mjs +113 -0
  10. package/dist/context.mjs.map +1 -0
  11. package/dist/control-DFOg_pc_.d.cts +1027 -0
  12. package/dist/control-DaXBm-52.d.ts +1027 -0
  13. package/dist/gridCustomizer-C0V9FAE_.d.ts +569 -0
  14. package/dist/gridCustomizer-mJO-kmQ4.d.cts +569 -0
  15. package/dist/hooks.cjs +85 -0
  16. package/dist/hooks.cjs.map +1 -0
  17. package/dist/hooks.d.cts +24 -0
  18. package/dist/hooks.d.ts +24 -0
  19. package/dist/hooks.mjs +60 -0
  20. package/dist/hooks.mjs.map +1 -0
  21. package/dist/icons.cjs +202 -0
  22. package/dist/icons.cjs.map +1 -0
  23. package/dist/icons.d.cts +130 -0
  24. package/dist/icons.d.ts +130 -0
  25. package/dist/icons.mjs +165 -0
  26. package/dist/icons.mjs.map +1 -0
  27. package/dist/index.cjs +6509 -0
  28. package/dist/index.cjs.map +1 -0
  29. package/dist/index.d.cts +410 -0
  30. package/dist/index.d.ts +410 -0
  31. package/dist/index.mjs +6490 -0
  32. package/dist/index.mjs.map +1 -0
  33. package/dist/runtime-capabilities-BdGDdu0d.d.cts +119 -0
  34. package/dist/runtime-capabilities-Brfc7loJ.d.ts +119 -0
  35. package/dist/theme-BfeZIxmZ.d.cts +74 -0
  36. package/dist/theme-BfeZIxmZ.d.ts +74 -0
  37. package/dist/theme.cjs +215 -0
  38. package/dist/theme.cjs.map +1 -0
  39. package/dist/theme.d.cts +32 -0
  40. package/dist/theme.d.ts +32 -0
  41. package/dist/theme.mjs +186 -0
  42. package/dist/theme.mjs.map +1 -0
  43. package/dist/types.cjs +976 -0
  44. package/dist/types.cjs.map +1 -0
  45. package/dist/types.d.cts +813 -0
  46. package/dist/types.d.ts +813 -0
  47. package/dist/types.mjs +902 -0
  48. package/dist/types.mjs.map +1 -0
  49. package/dist/utils.cjs +250 -0
  50. package/dist/utils.cjs.map +1 -0
  51. package/dist/utils.d.cts +99 -0
  52. package/dist/utils.d.ts +99 -0
  53. package/dist/utils.mjs +220 -0
  54. package/dist/utils.mjs.map +1 -0
  55. package/dist/v8.cjs +4622 -0
  56. package/dist/v8.cjs.map +1 -0
  57. package/dist/v8.d.cts +730 -0
  58. package/dist/v8.d.ts +730 -0
  59. package/dist/v8.mjs +4622 -0
  60. package/dist/v8.mjs.map +1 -0
  61. package/dist/v9.cjs +19 -0
  62. package/dist/v9.cjs.map +1 -0
  63. package/dist/v9.d.cts +2 -0
  64. package/dist/v9.d.ts +2 -0
  65. package/dist/v9.mjs +1 -0
  66. package/dist/v9.mjs.map +1 -0
  67. package/package.json +113 -0
@@ -0,0 +1,24 @@
1
+ import { x as ControlDefinition } from './control-DFOg_pc_.cjs';
2
+ import { T as TimelineItem } from './runtime-capabilities-BdGDdu0d.cjs';
3
+ import './theme-BfeZIxmZ.cjs';
4
+
5
+ interface UseLiveDataResult {
6
+ records: Record<string, unknown>[] | null;
7
+ loading: boolean;
8
+ error: string | null;
9
+ fetchXmlAttributes: string[];
10
+ timelineItems: TimelineItem[] | null;
11
+ }
12
+ /**
13
+ * Subscribe to live records / timeline activities for a bound control.
14
+ * Calls `FormRuntimeCapabilities.fetchLiveData` on mount + whenever the
15
+ * control reference changes. Returns the empty/no-context shape when no
16
+ * provider wraps the caller (the deployed runtime is expected to wrap;
17
+ * tests can use the un-wrapped shape).
18
+ *
19
+ * The capability returns raw data; this hook adds the React state
20
+ * machinery (loading flag, error string, abort on unmount).
21
+ */
22
+ declare function useLiveData(control: ControlDefinition, enabled?: boolean): UseLiveDataResult;
23
+
24
+ export { type UseLiveDataResult, useLiveData };
@@ -0,0 +1,24 @@
1
+ import { x as ControlDefinition } from './control-DaXBm-52.js';
2
+ import { T as TimelineItem } from './runtime-capabilities-Brfc7loJ.js';
3
+ import './theme-BfeZIxmZ.js';
4
+
5
+ interface UseLiveDataResult {
6
+ records: Record<string, unknown>[] | null;
7
+ loading: boolean;
8
+ error: string | null;
9
+ fetchXmlAttributes: string[];
10
+ timelineItems: TimelineItem[] | null;
11
+ }
12
+ /**
13
+ * Subscribe to live records / timeline activities for a bound control.
14
+ * Calls `FormRuntimeCapabilities.fetchLiveData` on mount + whenever the
15
+ * control reference changes. Returns the empty/no-context shape when no
16
+ * provider wraps the caller (the deployed runtime is expected to wrap;
17
+ * tests can use the un-wrapped shape).
18
+ *
19
+ * The capability returns raw data; this hook adds the React state
20
+ * machinery (loading flag, error string, abort on unmount).
21
+ */
22
+ declare function useLiveData(control: ControlDefinition, enabled?: boolean): UseLiveDataResult;
23
+
24
+ export { type UseLiveDataResult, useLiveData };
package/dist/hooks.mjs ADDED
@@ -0,0 +1,60 @@
1
+ // src/hooks.ts
2
+ import { useEffect, useState } from "react";
3
+
4
+ // src/context/FormRuntimeContext.tsx
5
+ import { createContext, useContext } from "react";
6
+ import { jsx } from "react/jsx-runtime";
7
+ var FormRuntimeContext = createContext(null);
8
+ FormRuntimeContext.displayName = "FormRuntimeContext";
9
+ function useOptionalFormRuntimeContext() {
10
+ return useContext(FormRuntimeContext);
11
+ }
12
+
13
+ // src/hooks.ts
14
+ function useLiveData(control, enabled = true) {
15
+ const ctx = useOptionalFormRuntimeContext();
16
+ const [records, setRecords] = useState(null);
17
+ const [loading, setLoading] = useState(false);
18
+ const [error, setError] = useState(null);
19
+ const [fetchXmlAttributes, setFetchXmlAttributes] = useState([]);
20
+ const [timelineItems, setTimelineItems] = useState(null);
21
+ const fetchLiveData = ctx?.fetchLiveData;
22
+ const propertiesKey = JSON.stringify(control.properties ?? {});
23
+ const dataBindingKey = JSON.stringify(control.dataBinding ?? {});
24
+ useEffect(() => {
25
+ if (!enabled || !fetchLiveData) {
26
+ setRecords(null);
27
+ setLoading(false);
28
+ setError(null);
29
+ setTimelineItems(null);
30
+ setFetchXmlAttributes([]);
31
+ return;
32
+ }
33
+ let cancelled = false;
34
+ const controller = new AbortController();
35
+ setLoading(true);
36
+ setError(null);
37
+ fetchLiveData(control, { signal: controller.signal }).then((data) => {
38
+ if (cancelled) return;
39
+ setRecords(data.records);
40
+ setFetchXmlAttributes(data.fetchXmlAttributes);
41
+ setTimelineItems(data.timelineItems);
42
+ setLoading(false);
43
+ }).catch((err) => {
44
+ if (cancelled) return;
45
+ setError(err instanceof Error ? err.message : "Failed to fetch live data");
46
+ setRecords(null);
47
+ setTimelineItems(null);
48
+ setLoading(false);
49
+ });
50
+ return () => {
51
+ cancelled = true;
52
+ controller.abort();
53
+ };
54
+ }, [fetchLiveData, enabled, control.type, control.name, propertiesKey, dataBindingKey]);
55
+ return { records, loading, error, fetchXmlAttributes, timelineItems };
56
+ }
57
+ export {
58
+ useLiveData
59
+ };
60
+ //# sourceMappingURL=hooks.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks.ts","../src/context/FormRuntimeContext.tsx"],"sourcesContent":["// @dataverse-kit/form-runtime/hooks — FluentUI-agnostic React hooks.\n//\n// Today: `useLiveData` — wraps `FormRuntimeCapabilities.fetchLiveData`\n// with React-state choreography (loading / error / records /\n// timelineItems / fetchXmlAttributes). Used by the runtime's subgrid\n// and timeline per-type branches.\n//\n// Planned: useSubgridData, useChartData, useLookupSearch, useFormState,\n// useDirtyTracker (scaffolds; populated when their consumers move into\n// form-runtime).\n\nimport { useEffect, useState } from 'react';\nimport type { ControlDefinition } from './types';\nimport type { LiveDataResult, TimelineItem } from './types/runtime-capabilities';\nimport { useOptionalFormRuntimeContext } from './context/FormRuntimeContext';\n\nexport interface UseLiveDataResult {\n records: Record<string, unknown>[] | null;\n loading: boolean;\n error: string | null;\n fetchXmlAttributes: string[];\n timelineItems: TimelineItem[] | null;\n}\n\n/**\n * Subscribe to live records / timeline activities for a bound control.\n * Calls `FormRuntimeCapabilities.fetchLiveData` on mount + whenever the\n * control reference changes. Returns the empty/no-context shape when no\n * provider wraps the caller (the deployed runtime is expected to wrap;\n * tests can use the un-wrapped shape).\n *\n * The capability returns raw data; this hook adds the React state\n * machinery (loading flag, error string, abort on unmount).\n */\nexport function useLiveData(control: ControlDefinition, enabled: boolean = true): UseLiveDataResult {\n const ctx = useOptionalFormRuntimeContext();\n const [records, setRecords] = useState<Record<string, unknown>[] | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [fetchXmlAttributes, setFetchXmlAttributes] = useState<string[]>([]);\n const [timelineItems, setTimelineItems] = useState<TimelineItem[] | null>(null);\n\n // The hook fires on stable primitive deps only — `control` and `ctx`\n // are referentially unstable each render (FormRuntime walks the tree;\n // capabilities memo rebuilds when callbacks change), and depending on\n // them caused an abort/refetch loop. The fetcher reference, control\n // identity, and a hash of the properties that affect the query are\n // what actually matter; everything else is a noisy false positive.\n const fetchLiveData = ctx?.fetchLiveData;\n const propertiesKey = JSON.stringify(control.properties ?? {});\n const dataBindingKey = JSON.stringify(control.dataBinding ?? {});\n\n useEffect(() => {\n if (!enabled || !fetchLiveData) {\n setRecords(null);\n setLoading(false);\n setError(null);\n setTimelineItems(null);\n setFetchXmlAttributes([]);\n return;\n }\n\n let cancelled = false;\n const controller = new AbortController();\n setLoading(true);\n setError(null);\n\n fetchLiveData(control, { signal: controller.signal })\n .then((data: LiveDataResult) => {\n if (cancelled) return;\n setRecords(data.records);\n setFetchXmlAttributes(data.fetchXmlAttributes);\n setTimelineItems(data.timelineItems);\n setLoading(false);\n })\n .catch((err: unknown) => {\n if (cancelled) return;\n setError(err instanceof Error ? err.message : 'Failed to fetch live data');\n setRecords(null);\n setTimelineItems(null);\n setLoading(false);\n });\n\n return () => {\n cancelled = true;\n controller.abort();\n };\n // `control` is read once per fetch call but isn't a dep — its\n // identity churns each parent render. The `*Key` strings cover\n // the actual inputs the capability reads from `control`.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fetchLiveData, enabled, control.type, control.name, propertiesKey, dataBindingKey]);\n\n return { records, loading, error, fetchXmlAttributes, timelineItems };\n}\n","import React, { createContext, useContext } from 'react';\nimport type { FormRuntimeCapabilities } from '../types/runtime-capabilities';\n\n/**\n * Context that exposes editor- or host-supplied async capabilities to\n * the runtime's controls.\n *\n * Two implementations exist (Phase 1 Task 6.5 onwards):\n * - `EditorFormRuntimeProvider` in `apps/form-builder/src/contexts/` —\n * wires capabilities to the form-builder's Zustand stores (designer,\n * dataverse, previewRecord, gridCustomizer).\n * - Generated host code's provider (Phase 3) — wires capabilities to\n * `IApiService` from `@dataverse-kit/api-service`.\n *\n * Per `feedback_v1_migrations`, the runtime DOES NOT define a default\n * mock or no-op provider. Controls that depend on capabilities throw if\n * the consumer hasn't wrapped them in a provider — the error names the\n * provider that's expected, so the failure points at the integration\n * gap rather than masking it with silent no-ops.\n */\nconst FormRuntimeContext = createContext<FormRuntimeCapabilities | null>(null);\n\nFormRuntimeContext.displayName = 'FormRuntimeContext';\n\nexport interface FormRuntimeProviderProps {\n capabilities: FormRuntimeCapabilities;\n children: React.ReactNode;\n}\n\n/**\n * Provider wrapper. Caller supplies a `FormRuntimeCapabilities` value;\n * descendants read it via `useFormRuntimeContext()`. Wrap the runtime's\n * mount point (`<FormRuntime>`) with this; failing to do so causes\n * capability-consuming controls to throw on first render.\n */\nexport const FormRuntimeProvider: React.FC<FormRuntimeProviderProps> = ({\n capabilities,\n children,\n}) => <FormRuntimeContext.Provider value={capabilities}>{children}</FormRuntimeContext.Provider>;\n\n/**\n * Hook for runtime-internal callers that REQUIRE capabilities. Throws\n * with a directed error message if no provider is present so the\n * integration gap is visible at the call site (rather than a vague\n * \"Cannot read properties of null\" that points at the consumer).\n */\nexport function useFormRuntimeContext(): FormRuntimeCapabilities {\n const value = useContext(FormRuntimeContext);\n if (value === null) {\n throw new Error(\n '[@dataverse-kit/form-runtime] useFormRuntimeContext was called outside of a ' +\n '<FormRuntimeProvider>. Wrap your <FormRuntime> mount with a provider that ' +\n 'supplies FormRuntimeCapabilities (the editor app uses ' +\n 'EditorFormRuntimeProvider; generated host code uses ServiceFactory-backed ' +\n 'capabilities). See packages/form-runtime/src/context/FormRuntimeContext.tsx.',\n );\n }\n return value;\n}\n\n/**\n * Same as `useFormRuntimeContext()` but returns `null` when no provider\n * is present. Use for OPTIONAL capability access — controls that have a\n * sensible offline rendering (e.g. timeline, which renders a placeholder\n * when not connected) prefer this over the throwing variant.\n */\nexport function useOptionalFormRuntimeContext(): FormRuntimeCapabilities | null {\n return useContext(FormRuntimeContext);\n}\n"],"mappings":";AAWA,SAAS,WAAW,gBAAgB;;;ACXpC,SAAgB,eAAe,kBAAkB;AAsC3C;AAlBN,IAAM,qBAAqB,cAA8C,IAAI;AAE7E,mBAAmB,cAAc;AA4C1B,SAAS,gCAAgE;AAC9E,SAAO,WAAW,kBAAkB;AACtC;;;ADlCO,SAAS,YAAY,SAA4B,UAAmB,MAAyB;AAClG,QAAM,MAAM,8BAA8B;AAC1C,QAAM,CAAC,SAAS,UAAU,IAAI,SAA2C,IAAI;AAC7E,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AACtD,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAAmB,CAAC,CAAC;AACzE,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAgC,IAAI;AAQ9E,QAAM,gBAAgB,KAAK;AAC3B,QAAM,gBAAgB,KAAK,UAAU,QAAQ,cAAc,CAAC,CAAC;AAC7D,QAAM,iBAAiB,KAAK,UAAU,QAAQ,eAAe,CAAC,CAAC;AAE/D,YAAU,MAAM;AACd,QAAI,CAAC,WAAW,CAAC,eAAe;AAC9B,iBAAW,IAAI;AACf,iBAAW,KAAK;AAChB,eAAS,IAAI;AACb,uBAAiB,IAAI;AACrB,4BAAsB,CAAC,CAAC;AACxB;AAAA,IACF;AAEA,QAAI,YAAY;AAChB,UAAM,aAAa,IAAI,gBAAgB;AACvC,eAAW,IAAI;AACf,aAAS,IAAI;AAEb,kBAAc,SAAS,EAAE,QAAQ,WAAW,OAAO,CAAC,EACjD,KAAK,CAAC,SAAyB;AAC9B,UAAI,UAAW;AACf,iBAAW,KAAK,OAAO;AACvB,4BAAsB,KAAK,kBAAkB;AAC7C,uBAAiB,KAAK,aAAa;AACnC,iBAAW,KAAK;AAAA,IAClB,CAAC,EACA,MAAM,CAAC,QAAiB;AACvB,UAAI,UAAW;AACf,eAAS,eAAe,QAAQ,IAAI,UAAU,2BAA2B;AACzE,iBAAW,IAAI;AACf,uBAAiB,IAAI;AACrB,iBAAW,KAAK;AAAA,IAClB,CAAC;AAEH,WAAO,MAAM;AACX,kBAAY;AACZ,iBAAW,MAAM;AAAA,IACnB;AAAA,EAKF,GAAG,CAAC,eAAe,SAAS,QAAQ,MAAM,QAAQ,MAAM,eAAe,cAAc,CAAC;AAEtF,SAAO,EAAE,SAAS,SAAS,OAAO,oBAAoB,cAAc;AACtE;","names":[]}
package/dist/icons.cjs ADDED
@@ -0,0 +1,202 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/icons/index.ts
21
+ var icons_exports = {};
22
+ __export(icons_exports, {
23
+ V8_ICONS_WITHOUT_V9: () => V8_ICONS_WITHOUT_V9,
24
+ V8_PERSONA_SIZE_TO_V9: () => V8_PERSONA_SIZE_TO_V9,
25
+ V8_PRESENCE_TO_V9_STATUS: () => V8_PRESENCE_TO_V9_STATUS,
26
+ V8_TO_V9_ICON_MAP: () => V8_TO_V9_ICON_MAP,
27
+ buildV9IconImport: () => buildV9IconImport,
28
+ mapV8IconToV9: () => mapV8IconToV9,
29
+ mapV8PersonaSizeToV9: () => mapV8PersonaSizeToV9,
30
+ mapV8PresenceToV9Status: () => mapV8PresenceToV9Status,
31
+ sanitizeV8EnumIdentifier: () => sanitizeV8EnumIdentifier,
32
+ sanitizeV8PersonaSizeName: () => sanitizeV8PersonaSizeName,
33
+ sanitizeV8PresenceName: () => sanitizeV8PresenceName
34
+ });
35
+ module.exports = __toCommonJS(icons_exports);
36
+
37
+ // src/icons/iconNameMap.ts
38
+ var V8_TO_V9_ICON_MAP = {
39
+ Accept: "Checkmark20Regular",
40
+ Add: "Add20Regular",
41
+ AddTo: "AddSquare20Regular",
42
+ AlignCenter: "TextAlignCenter20Regular",
43
+ AlignLeft: "TextAlignLeft20Regular",
44
+ AlignRight: "TextAlignRight20Regular",
45
+ Back: "ArrowLeft20Regular",
46
+ Blocked2: "Prohibited20Regular",
47
+ BucketColor: "PaintBucket20Regular",
48
+ BulkUpload: "CloudArrowUp20Regular",
49
+ BulletedList: "TextBulletList20Regular",
50
+ CalculatorAddition: "Calculator20Regular",
51
+ Calendar: "Calendar20Regular",
52
+ Cancel: "Dismiss20Regular",
53
+ CellPhone: "Phone20Regular",
54
+ CheckList: "ClipboardTaskList20Regular",
55
+ CheckMark: "Checkmark20Regular",
56
+ ChevronDown: "ChevronDown20Regular",
57
+ ChevronLeft: "ChevronLeft20Regular",
58
+ ChevronRight: "ChevronRight20Regular",
59
+ ChevronUp: "ChevronUp20Regular",
60
+ CirclePause: "Pause20Regular",
61
+ CityNext: "BuildingMultiple20Regular",
62
+ Clear: "Dismiss20Regular",
63
+ Clock: "Clock20Regular",
64
+ CloudDownload: "CloudArrowDown20Regular",
65
+ CloudUpload: "CloudArrowUp20Regular",
66
+ Code: "Code20Regular",
67
+ Color: "Color20Regular",
68
+ ColumnOptions: "TableSettings20Regular",
69
+ Comment: "Comment20Regular",
70
+ Contact: "Person20Regular",
71
+ Copy: "Copy20Regular",
72
+ CustomList: "TextBulletList20Regular",
73
+ Database: "Database20Regular",
74
+ Delete: "Delete20Regular",
75
+ Down: "ArrowDown20Regular",
76
+ Download: "ArrowDownload20Regular",
77
+ Edit: "Edit20Regular",
78
+ ErrorBadge: "ErrorCircle20Regular",
79
+ FabricFolder: "Folder20Regular",
80
+ FabricOpenFolderHorizontal: "FolderOpen20Regular",
81
+ FavoriteStar: "Star20Regular",
82
+ FavoriteStarFill: "Star20Filled",
83
+ Filter: "Filter20Regular",
84
+ FitPage: "AutoFitWidth20Regular",
85
+ Flow: "Flow20Regular",
86
+ FullScreen: "FullScreenMaximize20Regular",
87
+ GridViewMedium: "Grid20Regular",
88
+ GridViewSmall: "Grid20Regular",
89
+ GroupObject: "Group20Regular",
90
+ Header1: "TextHeader120Regular",
91
+ History: "History20Regular",
92
+ Info: "Info20Regular",
93
+ Leave: "SignOut20Regular",
94
+ Link: "Link20Regular",
95
+ List: "TextBulletList20Regular",
96
+ Lock: "LockClosed20Regular",
97
+ Mail: "Mail20Regular",
98
+ Money: "Money20Regular",
99
+ More: "MoreHorizontal20Regular",
100
+ MoreVertical: "MoreVertical20Regular",
101
+ MoveToFolder: "FolderArrowRight20Regular",
102
+ NumberSymbol: "NumberSymbol20Regular",
103
+ OpenFolderHorizontal: "FolderOpen20Regular",
104
+ OpenInNewTab: "Open20Regular",
105
+ OpenInNewWindow: "Open20Regular",
106
+ Package: "Box20Regular",
107
+ PageHeaderEdit: "Edit20Regular",
108
+ Permissions: "ShieldCheckmark20Regular",
109
+ Phone: "Phone20Regular",
110
+ PhotoCollection: "ImageMultiple20Regular",
111
+ PlugDisconnected: "PlugDisconnected20Regular",
112
+ Redo: "ArrowRedo20Regular",
113
+ Refresh: "ArrowSync20Regular",
114
+ Remove: "Subtract20Regular",
115
+ Rename: "Rename20Regular",
116
+ Save: "Save20Regular",
117
+ SaveAndClose: "SaveEdit20Regular",
118
+ SaveTemplate: "SaveCopy20Regular",
119
+ Search: "Search20Regular",
120
+ Settings: "Settings20Regular",
121
+ Shapes: "Shapes20Regular",
122
+ SidePanel: "PanelRight20Regular",
123
+ Spacer: "TextWrap20Regular",
124
+ Star: "Star20Regular",
125
+ StatusCircleCheckmark: "CheckmarkCircle20Regular",
126
+ Switch: "ArrowSwap20Regular",
127
+ TVMonitor: "Tv20Regular",
128
+ Table: "Table20Regular",
129
+ TableGroup: "TableSimple20Regular",
130
+ Tablet: "Tablet20Regular",
131
+ TestPlan: "ClipboardTaskList20Regular",
132
+ TriggerAuto: "Flash20Regular",
133
+ Undo: "ArrowUndo20Regular",
134
+ Up: "ArrowUp20Regular",
135
+ Upload: "ArrowUpload20Regular",
136
+ View: "Eye20Regular",
137
+ Warning: "Warning20Regular",
138
+ ZipFolder: "FolderZip20Regular",
139
+ ZoomIn: "ZoomIn20Regular",
140
+ ZoomOut: "ZoomOut20Regular"
141
+ };
142
+ var V8_ICONS_WITHOUT_V9 = /* @__PURE__ */ new Set();
143
+ function mapV8IconToV9(v8Name) {
144
+ return V8_TO_V9_ICON_MAP[v8Name] ?? null;
145
+ }
146
+ function buildV9IconImport(v9IconNames) {
147
+ const sorted = Array.from(new Set(v9IconNames)).sort();
148
+ if (sorted.length === 0) return "";
149
+ return `import { ${sorted.join(", ")} } from '@fluentui/react-icons';
150
+ `;
151
+ }
152
+
153
+ // src/icons/personaCompatibilityMaps.ts
154
+ var V8_PERSONA_SIZE_TO_V9 = {
155
+ size8: 16,
156
+ size24: 24,
157
+ size32: 32,
158
+ size40: 40,
159
+ size48: 48,
160
+ size56: 56,
161
+ size72: 72,
162
+ size100: 96,
163
+ size120: 120
164
+ };
165
+ var V8_PRESENCE_TO_V9_STATUS = {
166
+ online: "available",
167
+ offline: "offline",
168
+ away: "away",
169
+ busy: "busy",
170
+ dnd: "do-not-disturb",
171
+ blocked: "unknown"
172
+ };
173
+ function mapV8PersonaSizeToV9(v8Size) {
174
+ return V8_PERSONA_SIZE_TO_V9[v8Size] ?? 48;
175
+ }
176
+ function mapV8PresenceToV9Status(v8Presence) {
177
+ return V8_PRESENCE_TO_V9_STATUS[v8Presence] ?? null;
178
+ }
179
+ function sanitizeV8EnumIdentifier(value, fallback) {
180
+ return /^[a-zA-Z][a-zA-Z0-9]*$/.test(value) ? value : fallback;
181
+ }
182
+ function sanitizeV8PresenceName(v8Presence) {
183
+ return sanitizeV8EnumIdentifier(v8Presence, "none");
184
+ }
185
+ function sanitizeV8PersonaSizeName(v8Size) {
186
+ return sanitizeV8EnumIdentifier(v8Size, "size48");
187
+ }
188
+ // Annotate the CommonJS export names for ESM import in node:
189
+ 0 && (module.exports = {
190
+ V8_ICONS_WITHOUT_V9,
191
+ V8_PERSONA_SIZE_TO_V9,
192
+ V8_PRESENCE_TO_V9_STATUS,
193
+ V8_TO_V9_ICON_MAP,
194
+ buildV9IconImport,
195
+ mapV8IconToV9,
196
+ mapV8PersonaSizeToV9,
197
+ mapV8PresenceToV9Status,
198
+ sanitizeV8EnumIdentifier,
199
+ sanitizeV8PersonaSizeName,
200
+ sanitizeV8PresenceName
201
+ });
202
+ //# sourceMappingURL=icons.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/icons/index.ts","../src/icons/iconNameMap.ts","../src/icons/personaCompatibilityMaps.ts"],"sourcesContent":["// v8 → v9 compatibility maps for icons and Persona.\n//\n// Moved from packages/export-engine/src/generators/{iconNameMap,\n// personaCompatibilityMaps}.ts in Phase 1 of the WYSIWYG-canvas refactor.\n// The generator imports them back from here; the runtime's v9 entry (Phase\n// 4) consumes them when rendering live v9 controls. Single source of truth.\n\nexport * from './iconNameMap';\nexport * from './personaCompatibilityMaps';\n","/**\n * Phase 3f.0 — v8 → v9 icon name lookup table.\n *\n * Maps Fluent UI v8 icon names (used by the form-builder picker and\n * emitted as `iconName=\"...\"` strings) to their equivalent component\n * names in `@fluentui/react-icons` for v9 generated output.\n *\n * v9 react-icons naming convention: `${Glyph}${Size}${Variant}` —\n * - Size: 12 | 16 | 20 | 24 | 28 | 32 | 48\n * - Variant: Regular | Filled\n *\n * The form generator emits inline icons in buttons, headers, and\n * column actions. 20px Regular is the standard size for inline use,\n * matching v8's default rendering. Callers needing a different size\n * can override at the call site.\n *\n * Coverage: every icon name referenced by `iconName: 'X'` patterns\n * in the form-builder project (~100 glyphs). Generated by surveying\n * `grep -rE \"iconName: ['\\\"]\"` output across `src/` on 2026-05-01.\n *\n * **Excluded from the v9 map** (no clean v9 equivalent — emit warning\n * via Phase 3f.1's scanV9Compatibility):\n * - none currently; v9 react-icons covers all 100 surveyed glyphs.\n * If a future v8 icon name has no v9 mapping, add it to\n * V8_ICONS_WITHOUT_V9 below so the scanner reports it.\n */\n\n/** v9 component name from `@fluentui/react-icons`. */\nexport type V9IconName = string;\n\n/**\n * v8 → v9 icon-name lookup. v8 keys are the literal `iconName=\"...\"`\n * strings the form generator emits today. v9 values are the component\n * names exported by `@fluentui/react-icons` at the standard 20px Regular\n * size. Default to `Regular` over `Filled` — matches v8's default weight.\n *\n * Some v8 names map to renamed v9 glyphs (Cancel → Dismiss, More →\n * MoreHorizontal, Refresh → ArrowSync, Back → ArrowLeft, Down → ArrowDown,\n * Up → ArrowUp, View → Eye, Remove → Subtract, Leave → SignOut). The map\n * is the single source of truth for these renames.\n */\nexport const V8_TO_V9_ICON_MAP: Record<string, V9IconName> = {\n Accept: 'Checkmark20Regular',\n Add: 'Add20Regular',\n AddTo: 'AddSquare20Regular',\n AlignCenter: 'TextAlignCenter20Regular',\n AlignLeft: 'TextAlignLeft20Regular',\n AlignRight: 'TextAlignRight20Regular',\n Back: 'ArrowLeft20Regular',\n Blocked2: 'Prohibited20Regular',\n BucketColor: 'PaintBucket20Regular',\n BulkUpload: 'CloudArrowUp20Regular',\n BulletedList: 'TextBulletList20Regular',\n CalculatorAddition: 'Calculator20Regular',\n Calendar: 'Calendar20Regular',\n Cancel: 'Dismiss20Regular',\n CellPhone: 'Phone20Regular',\n CheckList: 'ClipboardTaskList20Regular',\n CheckMark: 'Checkmark20Regular',\n ChevronDown: 'ChevronDown20Regular',\n ChevronLeft: 'ChevronLeft20Regular',\n ChevronRight: 'ChevronRight20Regular',\n ChevronUp: 'ChevronUp20Regular',\n CirclePause: 'Pause20Regular',\n CityNext: 'BuildingMultiple20Regular',\n Clear: 'Dismiss20Regular',\n Clock: 'Clock20Regular',\n CloudDownload: 'CloudArrowDown20Regular',\n CloudUpload: 'CloudArrowUp20Regular',\n Code: 'Code20Regular',\n Color: 'Color20Regular',\n ColumnOptions: 'TableSettings20Regular',\n Comment: 'Comment20Regular',\n Contact: 'Person20Regular',\n Copy: 'Copy20Regular',\n CustomList: 'TextBulletList20Regular',\n Database: 'Database20Regular',\n Delete: 'Delete20Regular',\n Down: 'ArrowDown20Regular',\n Download: 'ArrowDownload20Regular',\n Edit: 'Edit20Regular',\n ErrorBadge: 'ErrorCircle20Regular',\n FabricFolder: 'Folder20Regular',\n FabricOpenFolderHorizontal: 'FolderOpen20Regular',\n FavoriteStar: 'Star20Regular',\n FavoriteStarFill: 'Star20Filled',\n Filter: 'Filter20Regular',\n FitPage: 'AutoFitWidth20Regular',\n Flow: 'Flow20Regular',\n FullScreen: 'FullScreenMaximize20Regular',\n GridViewMedium: 'Grid20Regular',\n GridViewSmall: 'Grid20Regular',\n GroupObject: 'Group20Regular',\n Header1: 'TextHeader120Regular',\n History: 'History20Regular',\n Info: 'Info20Regular',\n Leave: 'SignOut20Regular',\n Link: 'Link20Regular',\n List: 'TextBulletList20Regular',\n Lock: 'LockClosed20Regular',\n Mail: 'Mail20Regular',\n Money: 'Money20Regular',\n More: 'MoreHorizontal20Regular',\n MoreVertical: 'MoreVertical20Regular',\n MoveToFolder: 'FolderArrowRight20Regular',\n NumberSymbol: 'NumberSymbol20Regular',\n OpenFolderHorizontal: 'FolderOpen20Regular',\n OpenInNewTab: 'Open20Regular',\n OpenInNewWindow: 'Open20Regular',\n Package: 'Box20Regular',\n PageHeaderEdit: 'Edit20Regular',\n Permissions: 'ShieldCheckmark20Regular',\n Phone: 'Phone20Regular',\n PhotoCollection: 'ImageMultiple20Regular',\n PlugDisconnected: 'PlugDisconnected20Regular',\n Redo: 'ArrowRedo20Regular',\n Refresh: 'ArrowSync20Regular',\n Remove: 'Subtract20Regular',\n Rename: 'Rename20Regular',\n Save: 'Save20Regular',\n SaveAndClose: 'SaveEdit20Regular',\n SaveTemplate: 'SaveCopy20Regular',\n Search: 'Search20Regular',\n Settings: 'Settings20Regular',\n Shapes: 'Shapes20Regular',\n SidePanel: 'PanelRight20Regular',\n Spacer: 'TextWrap20Regular',\n Star: 'Star20Regular',\n StatusCircleCheckmark: 'CheckmarkCircle20Regular',\n Switch: 'ArrowSwap20Regular',\n TVMonitor: 'Tv20Regular',\n Table: 'Table20Regular',\n TableGroup: 'TableSimple20Regular',\n Tablet: 'Tablet20Regular',\n TestPlan: 'ClipboardTaskList20Regular',\n TriggerAuto: 'Flash20Regular',\n Undo: 'ArrowUndo20Regular',\n Up: 'ArrowUp20Regular',\n Upload: 'ArrowUpload20Regular',\n View: 'Eye20Regular',\n Warning: 'Warning20Regular',\n ZipFolder: 'FolderZip20Regular',\n ZoomIn: 'ZoomIn20Regular',\n ZoomOut: 'ZoomOut20Regular',\n};\n\n/**\n * v8 icons that have no clean v9 equivalent. Empty today — every\n * surveyed v8 name maps to a v9 glyph above. Reserved for future v8\n * names (e.g. esoteric Office-suite glyphs) that don't ship in\n * `@fluentui/react-icons`. Phase 3f.1's `scanV9Compatibility` reads\n * this set to flag forms that use them.\n */\nexport const V8_ICONS_WITHOUT_V9: ReadonlySet<string> = new Set<string>();\n\n/**\n * Look up a v9 icon component name for a v8 icon name. Returns null\n * if no mapping exists; callers should consult `V8_ICONS_WITHOUT_V9`\n * to decide whether to flag it as a compatibility issue or just emit\n * a generic fallback.\n *\n * @param v8Name v8 `iconName` string (e.g. 'Add', 'Cancel')\n * @returns v9 component name (e.g. 'Add20Regular') or null\n */\nexport function mapV8IconToV9(v8Name: string): V9IconName | null {\n return V8_TO_V9_ICON_MAP[v8Name] ?? null;\n}\n\n/**\n * Build the import statement string for a set of v9 icons. Used by\n * generators that need to emit `import { Add20Regular, Delete20Regular }\n * from '@fluentui/react-icons'`. Empty input returns empty string —\n * caller should not include the import block at all in that case.\n *\n * @param v9IconNames Set or array of v9 component names\n * @returns Single-line import statement, or empty string if none\n */\nexport function buildV9IconImport(v9IconNames: Iterable<string>): string {\n const sorted = Array.from(new Set(v9IconNames)).sort();\n if (sorted.length === 0) return '';\n return `import { ${sorted.join(', ')} } from '@fluentui/react-icons';\\n`;\n}\n","/**\n * Phase 3f.4 — v8 Persona ↔ v9 Avatar compatibility maps.\n *\n * Extracted from FormCodeGenerator.ts (review fix) so the maps live\n * next to `iconNameMap.ts` and follow the same convention. Keeps the\n * generator focused on emission and lets the maps evolve independently.\n *\n * Naming convention parity with `mapV8IconToV9` from `iconNameMap.ts`:\n * `mapV8XxxToV9` — explicit v8 → v9 direction in the function name.\n *\n * v8 PersonaSize and PersonaPresence are enum names (`size48`, `online`)\n * that v8 turned into runtime values via `PersonaSize.size48` etc. v9\n * Avatar takes a numeric `size` and v9 PresenceBadge takes a `status`\n * string — different shapes, hence the lookup tables.\n */\n\n/**\n * v8 PersonaSize enum name → v9 Avatar `size` numeric value.\n *\n * v9 Avatar accepts only a fixed set of sizes (16/20/24/28/32/36/40/48/56\n * /64/72/96/120/128). v8 has a slightly different set (size8/24/32/40/48\n * /56/72/100/120). Round to the nearest valid v9 size when v8 has no\n * direct match (size8→16, size100→96).\n */\nexport const V8_PERSONA_SIZE_TO_V9: Record<string, number> = {\n size8: 16,\n size24: 24,\n size32: 32,\n size40: 40,\n size48: 48,\n size56: 56,\n size72: 72,\n size100: 96,\n size120: 120,\n};\n\n/**\n * v8 PersonaPresence enum name → v9 PresenceBadge `status` value.\n *\n * Returns null for unknown inputs — caller omits the badge entirely.\n * (Default v8 sentinel `'none'` is also unknown here — it never reaches\n * this map because the call site guards against `presence === 'none'`.)\n */\nexport const V8_PRESENCE_TO_V9_STATUS: Record<string, string> = {\n online: 'available',\n offline: 'offline',\n away: 'away',\n busy: 'busy',\n dnd: 'do-not-disturb',\n blocked: 'unknown',\n};\n\n/** Look up the v9 Avatar size for a v8 PersonaSize enum name. Defaults to 48. */\nexport function mapV8PersonaSizeToV9(v8Size: string): number {\n return V8_PERSONA_SIZE_TO_V9[v8Size] ?? 48;\n}\n\n/**\n * Look up the v9 PresenceBadge status for a v8 PersonaPresence enum name.\n * Returns null for unrecognized inputs — caller omits the badge.\n */\nexport function mapV8PresenceToV9Status(v8Presence: string): string | null {\n return V8_PRESENCE_TO_V9_STATUS[v8Presence] ?? null;\n}\n\n/**\n * Phase 3f.4 review fix — sanitize a user-controlled string that's\n * about to be interpolated into a JS member-access expression like\n * `PersonaPresence.${name}` or `PersonaSize.${name}`. The v8 emission\n * generates raw JS code, so an unvalidated user value (`'} alert(1) //'`)\n * would close the expression and inject arbitrary code. Whitelist to\n * identifier-shaped tokens; fall back to `fallback` for anything else.\n *\n * Pure-regex check intentional — doesn't tie us to a specific v8 enum\n * (which can shift across Fluent v8 patches). If the runtime enum\n * lookup yields undefined for a legal-but-unknown identifier, v8\n * silently renders without that prop — same outcome as the fallback.\n *\n * Used by the v8 Persona emission for both `presence` and `size` props.\n */\nexport function sanitizeV8EnumIdentifier(value: string, fallback: string): string {\n return /^[a-zA-Z][a-zA-Z0-9]*$/.test(value) ? value : fallback;\n}\n\n/** v8 PersonaPresence sanitizer — fallback `'none'` (no presence shown). */\nexport function sanitizeV8PresenceName(v8Presence: string): string {\n return sanitizeV8EnumIdentifier(v8Presence, 'none');\n}\n\n/** v8 PersonaSize sanitizer — fallback `'size48'` (the v8 default). */\nexport function sanitizeV8PersonaSizeName(v8Size: string): string {\n return sanitizeV8EnumIdentifier(v8Size, 'size48');\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Phase 3f.0 — v8 → v9 icon name lookup table.
3
+ *
4
+ * Maps Fluent UI v8 icon names (used by the form-builder picker and
5
+ * emitted as `iconName="..."` strings) to their equivalent component
6
+ * names in `@fluentui/react-icons` for v9 generated output.
7
+ *
8
+ * v9 react-icons naming convention: `${Glyph}${Size}${Variant}` —
9
+ * - Size: 12 | 16 | 20 | 24 | 28 | 32 | 48
10
+ * - Variant: Regular | Filled
11
+ *
12
+ * The form generator emits inline icons in buttons, headers, and
13
+ * column actions. 20px Regular is the standard size for inline use,
14
+ * matching v8's default rendering. Callers needing a different size
15
+ * can override at the call site.
16
+ *
17
+ * Coverage: every icon name referenced by `iconName: 'X'` patterns
18
+ * in the form-builder project (~100 glyphs). Generated by surveying
19
+ * `grep -rE "iconName: ['\"]"` output across `src/` on 2026-05-01.
20
+ *
21
+ * **Excluded from the v9 map** (no clean v9 equivalent — emit warning
22
+ * via Phase 3f.1's scanV9Compatibility):
23
+ * - none currently; v9 react-icons covers all 100 surveyed glyphs.
24
+ * If a future v8 icon name has no v9 mapping, add it to
25
+ * V8_ICONS_WITHOUT_V9 below so the scanner reports it.
26
+ */
27
+ /** v9 component name from `@fluentui/react-icons`. */
28
+ type V9IconName = string;
29
+ /**
30
+ * v8 → v9 icon-name lookup. v8 keys are the literal `iconName="..."`
31
+ * strings the form generator emits today. v9 values are the component
32
+ * names exported by `@fluentui/react-icons` at the standard 20px Regular
33
+ * size. Default to `Regular` over `Filled` — matches v8's default weight.
34
+ *
35
+ * Some v8 names map to renamed v9 glyphs (Cancel → Dismiss, More →
36
+ * MoreHorizontal, Refresh → ArrowSync, Back → ArrowLeft, Down → ArrowDown,
37
+ * Up → ArrowUp, View → Eye, Remove → Subtract, Leave → SignOut). The map
38
+ * is the single source of truth for these renames.
39
+ */
40
+ declare const V8_TO_V9_ICON_MAP: Record<string, V9IconName>;
41
+ /**
42
+ * v8 icons that have no clean v9 equivalent. Empty today — every
43
+ * surveyed v8 name maps to a v9 glyph above. Reserved for future v8
44
+ * names (e.g. esoteric Office-suite glyphs) that don't ship in
45
+ * `@fluentui/react-icons`. Phase 3f.1's `scanV9Compatibility` reads
46
+ * this set to flag forms that use them.
47
+ */
48
+ declare const V8_ICONS_WITHOUT_V9: ReadonlySet<string>;
49
+ /**
50
+ * Look up a v9 icon component name for a v8 icon name. Returns null
51
+ * if no mapping exists; callers should consult `V8_ICONS_WITHOUT_V9`
52
+ * to decide whether to flag it as a compatibility issue or just emit
53
+ * a generic fallback.
54
+ *
55
+ * @param v8Name v8 `iconName` string (e.g. 'Add', 'Cancel')
56
+ * @returns v9 component name (e.g. 'Add20Regular') or null
57
+ */
58
+ declare function mapV8IconToV9(v8Name: string): V9IconName | null;
59
+ /**
60
+ * Build the import statement string for a set of v9 icons. Used by
61
+ * generators that need to emit `import { Add20Regular, Delete20Regular }
62
+ * from '@fluentui/react-icons'`. Empty input returns empty string —
63
+ * caller should not include the import block at all in that case.
64
+ *
65
+ * @param v9IconNames Set or array of v9 component names
66
+ * @returns Single-line import statement, or empty string if none
67
+ */
68
+ declare function buildV9IconImport(v9IconNames: Iterable<string>): string;
69
+
70
+ /**
71
+ * Phase 3f.4 — v8 Persona ↔ v9 Avatar compatibility maps.
72
+ *
73
+ * Extracted from FormCodeGenerator.ts (review fix) so the maps live
74
+ * next to `iconNameMap.ts` and follow the same convention. Keeps the
75
+ * generator focused on emission and lets the maps evolve independently.
76
+ *
77
+ * Naming convention parity with `mapV8IconToV9` from `iconNameMap.ts`:
78
+ * `mapV8XxxToV9` — explicit v8 → v9 direction in the function name.
79
+ *
80
+ * v8 PersonaSize and PersonaPresence are enum names (`size48`, `online`)
81
+ * that v8 turned into runtime values via `PersonaSize.size48` etc. v9
82
+ * Avatar takes a numeric `size` and v9 PresenceBadge takes a `status`
83
+ * string — different shapes, hence the lookup tables.
84
+ */
85
+ /**
86
+ * v8 PersonaSize enum name → v9 Avatar `size` numeric value.
87
+ *
88
+ * v9 Avatar accepts only a fixed set of sizes (16/20/24/28/32/36/40/48/56
89
+ * /64/72/96/120/128). v8 has a slightly different set (size8/24/32/40/48
90
+ * /56/72/100/120). Round to the nearest valid v9 size when v8 has no
91
+ * direct match (size8→16, size100→96).
92
+ */
93
+ declare const V8_PERSONA_SIZE_TO_V9: Record<string, number>;
94
+ /**
95
+ * v8 PersonaPresence enum name → v9 PresenceBadge `status` value.
96
+ *
97
+ * Returns null for unknown inputs — caller omits the badge entirely.
98
+ * (Default v8 sentinel `'none'` is also unknown here — it never reaches
99
+ * this map because the call site guards against `presence === 'none'`.)
100
+ */
101
+ declare const V8_PRESENCE_TO_V9_STATUS: Record<string, string>;
102
+ /** Look up the v9 Avatar size for a v8 PersonaSize enum name. Defaults to 48. */
103
+ declare function mapV8PersonaSizeToV9(v8Size: string): number;
104
+ /**
105
+ * Look up the v9 PresenceBadge status for a v8 PersonaPresence enum name.
106
+ * Returns null for unrecognized inputs — caller omits the badge.
107
+ */
108
+ declare function mapV8PresenceToV9Status(v8Presence: string): string | null;
109
+ /**
110
+ * Phase 3f.4 review fix — sanitize a user-controlled string that's
111
+ * about to be interpolated into a JS member-access expression like
112
+ * `PersonaPresence.${name}` or `PersonaSize.${name}`. The v8 emission
113
+ * generates raw JS code, so an unvalidated user value (`'} alert(1) //'`)
114
+ * would close the expression and inject arbitrary code. Whitelist to
115
+ * identifier-shaped tokens; fall back to `fallback` for anything else.
116
+ *
117
+ * Pure-regex check intentional — doesn't tie us to a specific v8 enum
118
+ * (which can shift across Fluent v8 patches). If the runtime enum
119
+ * lookup yields undefined for a legal-but-unknown identifier, v8
120
+ * silently renders without that prop — same outcome as the fallback.
121
+ *
122
+ * Used by the v8 Persona emission for both `presence` and `size` props.
123
+ */
124
+ declare function sanitizeV8EnumIdentifier(value: string, fallback: string): string;
125
+ /** v8 PersonaPresence sanitizer — fallback `'none'` (no presence shown). */
126
+ declare function sanitizeV8PresenceName(v8Presence: string): string;
127
+ /** v8 PersonaSize sanitizer — fallback `'size48'` (the v8 default). */
128
+ declare function sanitizeV8PersonaSizeName(v8Size: string): string;
129
+
130
+ export { V8_ICONS_WITHOUT_V9, V8_PERSONA_SIZE_TO_V9, V8_PRESENCE_TO_V9_STATUS, V8_TO_V9_ICON_MAP, type V9IconName, buildV9IconImport, mapV8IconToV9, mapV8PersonaSizeToV9, mapV8PresenceToV9Status, sanitizeV8EnumIdentifier, sanitizeV8PersonaSizeName, sanitizeV8PresenceName };
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Phase 3f.0 — v8 → v9 icon name lookup table.
3
+ *
4
+ * Maps Fluent UI v8 icon names (used by the form-builder picker and
5
+ * emitted as `iconName="..."` strings) to their equivalent component
6
+ * names in `@fluentui/react-icons` for v9 generated output.
7
+ *
8
+ * v9 react-icons naming convention: `${Glyph}${Size}${Variant}` —
9
+ * - Size: 12 | 16 | 20 | 24 | 28 | 32 | 48
10
+ * - Variant: Regular | Filled
11
+ *
12
+ * The form generator emits inline icons in buttons, headers, and
13
+ * column actions. 20px Regular is the standard size for inline use,
14
+ * matching v8's default rendering. Callers needing a different size
15
+ * can override at the call site.
16
+ *
17
+ * Coverage: every icon name referenced by `iconName: 'X'` patterns
18
+ * in the form-builder project (~100 glyphs). Generated by surveying
19
+ * `grep -rE "iconName: ['\"]"` output across `src/` on 2026-05-01.
20
+ *
21
+ * **Excluded from the v9 map** (no clean v9 equivalent — emit warning
22
+ * via Phase 3f.1's scanV9Compatibility):
23
+ * - none currently; v9 react-icons covers all 100 surveyed glyphs.
24
+ * If a future v8 icon name has no v9 mapping, add it to
25
+ * V8_ICONS_WITHOUT_V9 below so the scanner reports it.
26
+ */
27
+ /** v9 component name from `@fluentui/react-icons`. */
28
+ type V9IconName = string;
29
+ /**
30
+ * v8 → v9 icon-name lookup. v8 keys are the literal `iconName="..."`
31
+ * strings the form generator emits today. v9 values are the component
32
+ * names exported by `@fluentui/react-icons` at the standard 20px Regular
33
+ * size. Default to `Regular` over `Filled` — matches v8's default weight.
34
+ *
35
+ * Some v8 names map to renamed v9 glyphs (Cancel → Dismiss, More →
36
+ * MoreHorizontal, Refresh → ArrowSync, Back → ArrowLeft, Down → ArrowDown,
37
+ * Up → ArrowUp, View → Eye, Remove → Subtract, Leave → SignOut). The map
38
+ * is the single source of truth for these renames.
39
+ */
40
+ declare const V8_TO_V9_ICON_MAP: Record<string, V9IconName>;
41
+ /**
42
+ * v8 icons that have no clean v9 equivalent. Empty today — every
43
+ * surveyed v8 name maps to a v9 glyph above. Reserved for future v8
44
+ * names (e.g. esoteric Office-suite glyphs) that don't ship in
45
+ * `@fluentui/react-icons`. Phase 3f.1's `scanV9Compatibility` reads
46
+ * this set to flag forms that use them.
47
+ */
48
+ declare const V8_ICONS_WITHOUT_V9: ReadonlySet<string>;
49
+ /**
50
+ * Look up a v9 icon component name for a v8 icon name. Returns null
51
+ * if no mapping exists; callers should consult `V8_ICONS_WITHOUT_V9`
52
+ * to decide whether to flag it as a compatibility issue or just emit
53
+ * a generic fallback.
54
+ *
55
+ * @param v8Name v8 `iconName` string (e.g. 'Add', 'Cancel')
56
+ * @returns v9 component name (e.g. 'Add20Regular') or null
57
+ */
58
+ declare function mapV8IconToV9(v8Name: string): V9IconName | null;
59
+ /**
60
+ * Build the import statement string for a set of v9 icons. Used by
61
+ * generators that need to emit `import { Add20Regular, Delete20Regular }
62
+ * from '@fluentui/react-icons'`. Empty input returns empty string —
63
+ * caller should not include the import block at all in that case.
64
+ *
65
+ * @param v9IconNames Set or array of v9 component names
66
+ * @returns Single-line import statement, or empty string if none
67
+ */
68
+ declare function buildV9IconImport(v9IconNames: Iterable<string>): string;
69
+
70
+ /**
71
+ * Phase 3f.4 — v8 Persona ↔ v9 Avatar compatibility maps.
72
+ *
73
+ * Extracted from FormCodeGenerator.ts (review fix) so the maps live
74
+ * next to `iconNameMap.ts` and follow the same convention. Keeps the
75
+ * generator focused on emission and lets the maps evolve independently.
76
+ *
77
+ * Naming convention parity with `mapV8IconToV9` from `iconNameMap.ts`:
78
+ * `mapV8XxxToV9` — explicit v8 → v9 direction in the function name.
79
+ *
80
+ * v8 PersonaSize and PersonaPresence are enum names (`size48`, `online`)
81
+ * that v8 turned into runtime values via `PersonaSize.size48` etc. v9
82
+ * Avatar takes a numeric `size` and v9 PresenceBadge takes a `status`
83
+ * string — different shapes, hence the lookup tables.
84
+ */
85
+ /**
86
+ * v8 PersonaSize enum name → v9 Avatar `size` numeric value.
87
+ *
88
+ * v9 Avatar accepts only a fixed set of sizes (16/20/24/28/32/36/40/48/56
89
+ * /64/72/96/120/128). v8 has a slightly different set (size8/24/32/40/48
90
+ * /56/72/100/120). Round to the nearest valid v9 size when v8 has no
91
+ * direct match (size8→16, size100→96).
92
+ */
93
+ declare const V8_PERSONA_SIZE_TO_V9: Record<string, number>;
94
+ /**
95
+ * v8 PersonaPresence enum name → v9 PresenceBadge `status` value.
96
+ *
97
+ * Returns null for unknown inputs — caller omits the badge entirely.
98
+ * (Default v8 sentinel `'none'` is also unknown here — it never reaches
99
+ * this map because the call site guards against `presence === 'none'`.)
100
+ */
101
+ declare const V8_PRESENCE_TO_V9_STATUS: Record<string, string>;
102
+ /** Look up the v9 Avatar size for a v8 PersonaSize enum name. Defaults to 48. */
103
+ declare function mapV8PersonaSizeToV9(v8Size: string): number;
104
+ /**
105
+ * Look up the v9 PresenceBadge status for a v8 PersonaPresence enum name.
106
+ * Returns null for unrecognized inputs — caller omits the badge.
107
+ */
108
+ declare function mapV8PresenceToV9Status(v8Presence: string): string | null;
109
+ /**
110
+ * Phase 3f.4 review fix — sanitize a user-controlled string that's
111
+ * about to be interpolated into a JS member-access expression like
112
+ * `PersonaPresence.${name}` or `PersonaSize.${name}`. The v8 emission
113
+ * generates raw JS code, so an unvalidated user value (`'} alert(1) //'`)
114
+ * would close the expression and inject arbitrary code. Whitelist to
115
+ * identifier-shaped tokens; fall back to `fallback` for anything else.
116
+ *
117
+ * Pure-regex check intentional — doesn't tie us to a specific v8 enum
118
+ * (which can shift across Fluent v8 patches). If the runtime enum
119
+ * lookup yields undefined for a legal-but-unknown identifier, v8
120
+ * silently renders without that prop — same outcome as the fallback.
121
+ *
122
+ * Used by the v8 Persona emission for both `presence` and `size` props.
123
+ */
124
+ declare function sanitizeV8EnumIdentifier(value: string, fallback: string): string;
125
+ /** v8 PersonaPresence sanitizer — fallback `'none'` (no presence shown). */
126
+ declare function sanitizeV8PresenceName(v8Presence: string): string;
127
+ /** v8 PersonaSize sanitizer — fallback `'size48'` (the v8 default). */
128
+ declare function sanitizeV8PersonaSizeName(v8Size: string): string;
129
+
130
+ export { V8_ICONS_WITHOUT_V9, V8_PERSONA_SIZE_TO_V9, V8_PRESENCE_TO_V9_STATUS, V8_TO_V9_ICON_MAP, type V9IconName, buildV9IconImport, mapV8IconToV9, mapV8PersonaSizeToV9, mapV8PresenceToV9Status, sanitizeV8EnumIdentifier, sanitizeV8PersonaSizeName, sanitizeV8PresenceName };