@_linked/shape-ui 2.0.0 → 2.2.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 (210) hide show
  1. package/lib/esm/columns.d.ts +58 -0
  2. package/lib/esm/columns.js +173 -0
  3. package/lib/esm/columns.js.map +1 -0
  4. package/lib/esm/components/AddInstanceForms.d.ts +38 -0
  5. package/lib/esm/components/AddInstanceForms.js +143 -0
  6. package/lib/esm/components/AddInstanceForms.js.map +1 -0
  7. package/lib/esm/components/AddInstanceForms.module.css +12 -0
  8. package/lib/esm/components/BatchEditDrawer.d.ts +13 -0
  9. package/lib/esm/components/BatchEditDrawer.js +122 -0
  10. package/lib/esm/components/BatchEditDrawer.js.map +1 -0
  11. package/lib/esm/components/BatchEditDrawer.module.css +193 -0
  12. package/lib/esm/components/CustomMultiSelect.d.ts +26 -0
  13. package/lib/esm/components/CustomMultiSelect.js +344 -0
  14. package/lib/esm/components/CustomMultiSelect.js.map +1 -0
  15. package/lib/esm/components/CustomMultiSelect.module.css +291 -0
  16. package/lib/esm/components/DynamicFormField.d.ts +21 -0
  17. package/lib/esm/components/DynamicFormField.js +149 -0
  18. package/lib/esm/components/DynamicFormField.js.map +1 -0
  19. package/lib/esm/components/DynamicFormField.module.css +169 -0
  20. package/lib/esm/components/EditInstanceForms.d.ts +15 -0
  21. package/lib/esm/components/EditInstanceForms.js +118 -0
  22. package/lib/esm/components/EditInstanceForms.js.map +1 -0
  23. package/lib/esm/components/FilterBadge.d.ts +20 -0
  24. package/lib/esm/components/FilterBadge.js +26 -0
  25. package/lib/esm/components/FilterBadge.js.map +1 -0
  26. package/lib/esm/components/FilterBadge.module.css +25 -0
  27. package/lib/esm/components/FormField.d.ts +18 -0
  28. package/lib/esm/components/FormField.js +9 -0
  29. package/lib/esm/components/FormField.js.map +1 -0
  30. package/lib/esm/components/FormField.module.css +57 -0
  31. package/lib/esm/components/InstanceDeletionDialog.d.ts +17 -0
  32. package/lib/esm/components/InstanceDeletionDialog.js +83 -0
  33. package/lib/esm/components/InstanceDeletionDialog.js.map +1 -0
  34. package/lib/esm/components/InstanceDeletionDialog.module.css +59 -0
  35. package/lib/esm/components/InstanceOverview.d.ts +37 -0
  36. package/lib/esm/components/InstanceOverview.js +233 -0
  37. package/lib/esm/components/InstanceOverview.js.map +1 -0
  38. package/lib/esm/components/InstanceOverview.module.css +35 -0
  39. package/lib/esm/components/InstanceView.d.ts +29 -0
  40. package/lib/esm/components/InstanceView.js +97 -0
  41. package/lib/esm/components/InstanceView.js.map +1 -0
  42. package/lib/esm/components/InstanceView.module.css +157 -0
  43. package/lib/esm/components/NodeBadge.d.ts +25 -0
  44. package/lib/esm/components/NodeBadge.js +29 -0
  45. package/lib/esm/components/NodeBadge.js.map +1 -0
  46. package/lib/esm/components/NodeValuesEditor.d.ts +15 -0
  47. package/lib/esm/components/NodeValuesEditor.js +29 -0
  48. package/lib/esm/components/NodeValuesEditor.js.map +1 -0
  49. package/lib/esm/components/NodeValuesEditor.module.css +4 -0
  50. package/lib/esm/components/ReactTable.d.ts +50 -0
  51. package/lib/esm/components/ReactTable.js +370 -0
  52. package/lib/esm/components/ReactTable.js.map +1 -0
  53. package/lib/esm/components/ReactTable.module.css +950 -0
  54. package/lib/esm/components/TextfieldEditor.d.ts +1 -2
  55. package/lib/esm/components/TextfieldEditor.js +2 -2
  56. package/lib/esm/components/TextfieldEditor.js.map +1 -1
  57. package/lib/esm/components/forms.module.css +96 -0
  58. package/lib/esm/host.d.ts +196 -0
  59. package/lib/esm/host.js +25 -0
  60. package/lib/esm/host.js.map +1 -0
  61. package/lib/esm/hostContext.d.ts +34 -0
  62. package/lib/esm/hostContext.js +95 -0
  63. package/lib/esm/hostContext.js.map +1 -0
  64. package/lib/esm/index.d.ts +64 -10
  65. package/lib/esm/index.js +63 -14
  66. package/lib/esm/index.js.map +1 -1
  67. package/lib/esm/read.d.ts +48 -0
  68. package/lib/esm/read.js +96 -0
  69. package/lib/esm/read.js.map +1 -0
  70. package/lib/esm/search.d.ts +32 -0
  71. package/lib/esm/search.js +87 -0
  72. package/lib/esm/search.js.map +1 -0
  73. package/lib/esm/shape/contracts.d.ts +58 -0
  74. package/lib/esm/shape/contracts.js +15 -0
  75. package/lib/esm/shape/contracts.js.map +1 -0
  76. package/lib/esm/shape/naming.d.ts +30 -0
  77. package/lib/esm/shape/naming.js +52 -0
  78. package/lib/esm/shape/naming.js.map +1 -0
  79. package/lib/esm/shape/nodeDisplay.d.ts +36 -0
  80. package/lib/esm/shape/nodeDisplay.js +117 -0
  81. package/lib/esm/shape/nodeDisplay.js.map +1 -0
  82. package/lib/esm/shape/propertyTypes.d.ts +12 -0
  83. package/lib/esm/shape/propertyTypes.js +60 -0
  84. package/lib/esm/shape/propertyTypes.js.map +1 -0
  85. package/lib/esm/shape/propertyVisibility.d.ts +56 -0
  86. package/lib/esm/shape/propertyVisibility.js +112 -0
  87. package/lib/esm/shape/propertyVisibility.js.map +1 -0
  88. package/lib/esm/shape/shapeDependencies.d.ts +41 -0
  89. package/lib/esm/shape/shapeDependencies.js +141 -0
  90. package/lib/esm/shape/shapeDependencies.js.map +1 -0
  91. package/lib/esm/shape/tableFilters.d.ts +35 -0
  92. package/lib/esm/shape/tableFilters.js +171 -0
  93. package/lib/esm/shape/tableFilters.js.map +1 -0
  94. package/lib/esm/shape/useFormDependencies.d.ts +38 -0
  95. package/lib/esm/shape/useFormDependencies.js +178 -0
  96. package/lib/esm/shape/useFormDependencies.js.map +1 -0
  97. package/lib/esm/shape/validation.d.ts +15 -0
  98. package/lib/esm/shape/validation.js +106 -0
  99. package/lib/esm/shape/validation.js.map +1 -0
  100. package/lib/esm/tokens.css +25 -0
  101. package/lib/esm/types.d.ts +22 -0
  102. package/lib/esm/types.js +1 -0
  103. package/lib/esm/types.js.map +1 -0
  104. package/lib/esm/write.d.ts +51 -0
  105. package/lib/esm/write.js +99 -0
  106. package/lib/esm/write.js.map +1 -0
  107. package/package.json +44 -18
  108. package/src/backend.ts +1 -0
  109. package/src/columns.regression.test.ts +143 -0
  110. package/src/columns.test.ts +200 -0
  111. package/src/columns.ts +228 -0
  112. package/src/components/AddInstanceForms.module.css +12 -0
  113. package/src/components/AddInstanceForms.tsx +321 -0
  114. package/src/components/AvatarEditor.tsx +34 -0
  115. package/src/components/BatchEditDrawer.module.css +193 -0
  116. package/src/components/BatchEditDrawer.tsx +295 -0
  117. package/src/components/CheckboxEditor.module.css +6 -0
  118. package/src/components/CheckboxEditor.tsx +86 -0
  119. package/src/components/CustomMultiSelect.module.css +291 -0
  120. package/src/components/CustomMultiSelect.tsx +527 -0
  121. package/src/components/DateEditor.tsx +50 -0
  122. package/src/components/DynamicFormField.module.css +169 -0
  123. package/src/components/DynamicFormField.tsx +357 -0
  124. package/src/components/EditInstanceForms.tsx +260 -0
  125. package/src/components/FilterBadge.module.css +25 -0
  126. package/src/components/FilterBadge.tsx +70 -0
  127. package/src/components/FormField.module.css +57 -0
  128. package/src/components/FormField.tsx +59 -0
  129. package/src/components/ImageValueEditor.module.css +3 -0
  130. package/src/components/ImageValueEditor.tsx +82 -0
  131. package/src/components/InstanceDeletionDialog.module.css +59 -0
  132. package/src/components/InstanceDeletionDialog.tsx +175 -0
  133. package/src/components/InstanceOverview.module.css +35 -0
  134. package/src/components/InstanceOverview.tsx +374 -0
  135. package/src/components/InstanceView.module.css +157 -0
  136. package/src/components/InstanceView.tsx +212 -0
  137. package/src/components/NodeBadge.tsx +60 -0
  138. package/src/components/NodeValuesEditor.module.css +4 -0
  139. package/src/components/NodeValuesEditor.tsx +64 -0
  140. package/src/components/RadioButtonEditor.module.css +22 -0
  141. package/src/components/RadioButtonEditor.tsx +96 -0
  142. package/src/components/ReactTable.module.css +950 -0
  143. package/src/components/ReactTable.tsx +991 -0
  144. package/src/components/SelectEditor.tsx +85 -0
  145. package/src/components/ShapeTable.module.css +394 -0
  146. package/src/components/SwitchEditor.tsx +60 -0
  147. package/src/components/TextareaEditor.tsx +55 -0
  148. package/src/components/TextfieldEditor.tsx +67 -0
  149. package/src/components/ToggleEditor.tsx +63 -0
  150. package/src/components/forms.module.css +96 -0
  151. package/src/host.ts +226 -0
  152. package/src/hostContext.tsx +114 -0
  153. package/src/index.ts +99 -0
  154. package/src/package.ts +21 -0
  155. package/src/read.ts +148 -0
  156. package/src/search.test.ts +174 -0
  157. package/src/search.ts +108 -0
  158. package/src/shape/contracts.ts +66 -0
  159. package/src/shape/naming.ts +52 -0
  160. package/src/shape/nodeDisplay.ts +114 -0
  161. package/src/shape/propertyTypes.ts +86 -0
  162. package/src/shape/propertyVisibility.ts +180 -0
  163. package/src/shape/shapeDependencies.ts +183 -0
  164. package/src/shape/tableFilters.ts +223 -0
  165. package/src/shape/types.ts +1158 -0
  166. package/src/shape/useFormDependencies.ts +257 -0
  167. package/src/shape/validation.ts +121 -0
  168. package/src/tokens.css +25 -0
  169. package/src/types.ts +20 -0
  170. package/src/utils/helper.ts +35 -0
  171. package/src/write.test.ts +174 -0
  172. package/src/write.ts +114 -0
  173. package/.changeset/README.md +0 -20
  174. package/.changeset/config.json +0 -14
  175. package/.github/workflows/changeset-check.yml +0 -44
  176. package/.github/workflows/ci.yml +0 -43
  177. package/.github/workflows/publish.yml +0 -158
  178. package/CHANGELOG.md +0 -30
  179. package/lib/esm/components/AvatarEditor.d.ts +0 -20
  180. package/lib/esm/components/AvatarEditor.js +0 -7
  181. package/lib/esm/components/AvatarEditor.js.map +0 -1
  182. package/lib/esm/components/CheckboxEditor.d.ts +0 -21
  183. package/lib/esm/components/CheckboxEditor.js +0 -44
  184. package/lib/esm/components/CheckboxEditor.js.map +0 -1
  185. package/lib/esm/components/DateEditor.d.ts +0 -20
  186. package/lib/esm/components/DateEditor.js +0 -22
  187. package/lib/esm/components/DateEditor.js.map +0 -1
  188. package/lib/esm/components/RadioButtonEditor.d.ts +0 -23
  189. package/lib/esm/components/RadioButtonEditor.js +0 -41
  190. package/lib/esm/components/RadioButtonEditor.js.map +0 -1
  191. package/lib/esm/components/SelectEditor.d.ts +0 -21
  192. package/lib/esm/components/SelectEditor.js +0 -30
  193. package/lib/esm/components/SelectEditor.js.map +0 -1
  194. package/lib/esm/components/SwitchEditor.d.ts +0 -21
  195. package/lib/esm/components/SwitchEditor.js +0 -23
  196. package/lib/esm/components/SwitchEditor.js.map +0 -1
  197. package/lib/esm/components/TextareaEditor.d.ts +0 -23
  198. package/lib/esm/components/TextareaEditor.js +0 -15
  199. package/lib/esm/components/TextareaEditor.js.map +0 -1
  200. package/lib/esm/components/ToggleEditor.d.ts +0 -22
  201. package/lib/esm/components/ToggleEditor.js +0 -23
  202. package/lib/esm/components/ToggleEditor.js.map +0 -1
  203. package/lib/esm/ontologies/lincd-ui.d.ts +0 -6
  204. package/lib/esm/ontologies/lincd-ui.js +0 -18
  205. package/lib/esm/ontologies/lincd-ui.js.map +0 -1
  206. package/lib/esm/package.d.ts +0 -3
  207. package/lib/esm/package.js +0 -4
  208. package/lib/esm/package.js.map +0 -1
  209. package/tsconfig-cjs.json +0 -8
  210. package/tsconfig-esm.json +0 -9
@@ -0,0 +1,38 @@
1
+ import type { NodeShapeWire } from '@_linked/core/shapes/nodeShapeWire';
2
+ import { type PropertyDependency } from './shapeDependencies.js';
3
+ /**
4
+ * Dependency state for a single child field.
5
+ * Passed down to DynamicFormField via props.
6
+ */
7
+ export interface FieldDependencyState {
8
+ /** IDs the child should be narrowed to (null = show all, [] = show none) */
9
+ narrowedIds: string[] | null;
10
+ /** Whether the parent field has a value selected */
11
+ parentHasValue: boolean;
12
+ /** Human-readable parent labels (for "Select X first" hint) */
13
+ parentLabels: string[];
14
+ /** Whether narrowing data is currently being fetched */
15
+ loading: boolean;
16
+ }
17
+ /**
18
+ * Hook that computes and manages field dependencies for a form.
19
+ * Infers dependency relationships from the shape graph, tracks parent
20
+ * field changes, and fetches narrowing data.
21
+ */
22
+ /** Read one instance's data. Injected so this hook holds no control-plane dependency. */
23
+ export type ReadInstance = (shapeIri: string, instanceId: string) => Promise<{
24
+ rows: Record<string, unknown>[];
25
+ }>;
26
+ export declare function useFormDependencies(shape: NodeShapeWire | null, allShapes: Record<string, NodeShapeWire> | null, projectId: string | null, readInstance?: ReadInstance): {
27
+ dependencies: PropertyDependency[];
28
+ depMap: Map<string, PropertyDependency[]>;
29
+ narrowedIds: Map<string, string[]>;
30
+ parentHasValue: Map<string, boolean>;
31
+ loading: Map<string, boolean>;
32
+ onParentValueChange: (parentLabel: string, parentValue: any) => Promise<void>;
33
+ initFromData: (data: Record<string, any>) => void;
34
+ hasDependency: (label: string) => boolean;
35
+ isParent: (label: string) => boolean;
36
+ getParentLabels: (childLabel: string) => string[];
37
+ getDependencyState: (label: string) => FieldDependencyState | undefined;
38
+ };
@@ -0,0 +1,178 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ import { buildDependencyMap, computeDependencies, extractNarrowingIds, } from './shapeDependencies.js';
3
+ import { getShapeParamsFromUri } from './naming.js';
4
+ export function useFormDependencies(shape, allShapes, projectId, readInstance) {
5
+ // Compute static dependency graph (only changes when shape changes)
6
+ const dependencies = useMemo(() => {
7
+ if (!shape || !allShapes)
8
+ return [];
9
+ return computeDependencies(shape, allShapes);
10
+ }, [shape === null || shape === void 0 ? void 0 : shape.id, allShapes]);
11
+ const depMap = useMemo(() => buildDependencyMap(dependencies), [dependencies]);
12
+ // State for narrowing results
13
+ const [narrowedIds, setNarrowedIds] = useState(new Map());
14
+ const [parentHasValue, setParentHasValue] = useState(new Map());
15
+ const [loading, setLoading] = useState(new Map());
16
+ // Abort controllers for in-flight fetches
17
+ const fetchControllers = useRef(new Map());
18
+ /**
19
+ * Called when a parent field value changes.
20
+ * Fetches the parent instance data and extracts narrowing IDs for dependent fields.
21
+ */
22
+ const onParentValueChange = useCallback(async (parentLabel, parentValue) => {
23
+ // Find all dependencies where this property is the parent
24
+ const childDeps = dependencies.filter((d) => d.parentLabel === parentLabel);
25
+ if (childDeps.length === 0)
26
+ return;
27
+ // Extract parent instance ID
28
+ const parentId = parentValue
29
+ ? typeof parentValue === 'object'
30
+ ? parentValue.id
31
+ : typeof parentValue === 'string'
32
+ ? parentValue
33
+ : null
34
+ : null;
35
+ // Update parentHasValue for all children of this parent
36
+ setParentHasValue((prev) => {
37
+ const next = new Map(prev);
38
+ for (const dep of childDeps) {
39
+ next.set(dep.childLabel, !!parentId);
40
+ }
41
+ return next;
42
+ });
43
+ if (!parentId || !projectId) {
44
+ // Parent cleared — remove narrowing for all children
45
+ setNarrowedIds((prev) => {
46
+ const next = new Map(prev);
47
+ for (const dep of childDeps) {
48
+ next.set(dep.childLabel, null);
49
+ }
50
+ return next;
51
+ });
52
+ return;
53
+ }
54
+ // Cancel any in-flight fetch for this parent
55
+ const existing = fetchControllers.current.get(parentLabel);
56
+ if (existing)
57
+ existing.abort();
58
+ const controller = new AbortController();
59
+ fetchControllers.current.set(parentLabel, controller);
60
+ // Set loading state
61
+ setLoading((prev) => {
62
+ const next = new Map(prev);
63
+ for (const dep of childDeps) {
64
+ next.set(dep.childLabel, true);
65
+ }
66
+ return next;
67
+ });
68
+ try {
69
+ // Convert parent valueShape URI to package:label format for getInstanceData
70
+ const parentShapeParam = getShapeParamsFromUri(childDeps[0].parentValueShapeId);
71
+ if (!readInstance)
72
+ return;
73
+ const result = await readInstance(parentShapeParam, parentId);
74
+ if (controller.signal.aborted)
75
+ return;
76
+ const instanceData = Array.isArray(result === null || result === void 0 ? void 0 : result.rows)
77
+ ? result.rows[0]
78
+ : result === null || result === void 0 ? void 0 : result.rows;
79
+ if (!instanceData) {
80
+ // Could not fetch parent data — allow all options
81
+ setNarrowedIds((prev) => {
82
+ const next = new Map(prev);
83
+ for (const dep of childDeps) {
84
+ next.set(dep.childLabel, null);
85
+ }
86
+ return next;
87
+ });
88
+ return;
89
+ }
90
+ // Extract narrowing IDs for each child
91
+ setNarrowedIds((prev) => {
92
+ const next = new Map(prev);
93
+ for (const dep of childDeps) {
94
+ const ids = extractNarrowingIds(instanceData, dep.linkingPropertyLabel);
95
+ next.set(dep.childLabel, ids.length > 0 ? ids : null);
96
+ }
97
+ return next;
98
+ });
99
+ }
100
+ catch (err) {
101
+ if (!controller.signal.aborted) {
102
+ console.warn('Failed to fetch parent instance for narrowing:', err);
103
+ // On error, don't narrow (show all options)
104
+ setNarrowedIds((prev) => {
105
+ const next = new Map(prev);
106
+ for (const dep of childDeps) {
107
+ next.set(dep.childLabel, null);
108
+ }
109
+ return next;
110
+ });
111
+ }
112
+ }
113
+ finally {
114
+ if (!controller.signal.aborted) {
115
+ setLoading((prev) => {
116
+ const next = new Map(prev);
117
+ for (const dep of childDeps) {
118
+ next.set(dep.childLabel, false);
119
+ }
120
+ return next;
121
+ });
122
+ }
123
+ }
124
+ }, [dependencies, projectId]);
125
+ /**
126
+ * Initialize dependency state from existing form data (draft restore / edit mode).
127
+ * Call this after loading initial data to set parentHasValue for pre-filled fields.
128
+ */
129
+ const initFromData = useCallback((data) => {
130
+ if (!data)
131
+ return;
132
+ // Find all parent labels and trigger onParentValueChange for each that has a value
133
+ const parentLabels = new Set(dependencies.map((d) => d.parentLabel));
134
+ for (const label of parentLabels) {
135
+ if (data[label] !== undefined && data[label] !== null) {
136
+ onParentValueChange(label, data[label]);
137
+ }
138
+ }
139
+ }, [dependencies, onParentValueChange]);
140
+ // Cleanup on unmount
141
+ useEffect(() => {
142
+ return () => {
143
+ fetchControllers.current.forEach((c) => c.abort());
144
+ };
145
+ }, []);
146
+ /** Check if a property has any parent dependencies */
147
+ const hasDependency = useCallback((label) => depMap.has(label), [depMap]);
148
+ /** Check if a property is a parent (has children that depend on it) */
149
+ const isParent = useCallback((label) => dependencies.some((d) => d.parentLabel === label), [dependencies]);
150
+ /** Get the parent labels for a given child */
151
+ const getParentLabels = useCallback((childLabel) => (depMap.get(childLabel) || []).map((d) => d.parentLabel), [depMap]);
152
+ /** Build FieldDependencyState for a given property label */
153
+ const getDependencyState = useCallback((label) => {
154
+ var _a, _b, _c;
155
+ if (!depMap.has(label))
156
+ return undefined;
157
+ return {
158
+ narrowedIds: (_a = narrowedIds.get(label)) !== null && _a !== void 0 ? _a : null,
159
+ parentHasValue: (_b = parentHasValue.get(label)) !== null && _b !== void 0 ? _b : true,
160
+ parentLabels: getParentLabels(label),
161
+ loading: (_c = loading.get(label)) !== null && _c !== void 0 ? _c : false,
162
+ };
163
+ }, [depMap, narrowedIds, parentHasValue, loading, getParentLabels]);
164
+ return {
165
+ dependencies,
166
+ depMap,
167
+ narrowedIds,
168
+ parentHasValue,
169
+ loading,
170
+ onParentValueChange,
171
+ initFromData,
172
+ hasDependency,
173
+ isParent,
174
+ getParentLabels,
175
+ getDependencyState,
176
+ };
177
+ }
178
+ //# sourceMappingURL=useFormDependencies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFormDependencies.js","sourceRoot":"","sources":["../../../src/shape/useFormDependencies.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { PropertyShapeWire } from '@_linked/core/shapes/nodeShapeWire';
2
+ export interface FieldError {
3
+ propertyLabel: string;
4
+ message: string;
5
+ }
6
+ /**
7
+ * Validate a single field value against its PropertyShape constraints.
8
+ * Returns an error message string, or empty string if valid.
9
+ */
10
+ export declare function validateField(property: PropertyShapeWire, value: any): string;
11
+ /**
12
+ * Validate all fields at once (for submit-time gate).
13
+ * Returns an array of errors; empty array means all valid.
14
+ */
15
+ export declare function validateAllFields(properties: PropertyShapeWire[], data: Record<string, any>): FieldError[];
@@ -0,0 +1,106 @@
1
+ import { enumOptions } from './nodeDisplay.js';
2
+ import { shacl } from '@_linked/core/ontologies/shacl';
3
+ /**
4
+ * Validate a single field value against its PropertyShape constraints.
5
+ * Returns an error message string, or empty string if valid.
6
+ */
7
+ export function validateField(property, value) {
8
+ var _a;
9
+ const nodeKind = (_a = property.nodeKind) === null || _a === void 0 ? void 0 : _a.id;
10
+ const isIRI = nodeKind === shacl.IRI.id ||
11
+ nodeKind === shacl.BlankNode.id ||
12
+ nodeKind === shacl.BlankNodeOrIRI.id;
13
+ // Required check (minCount > 0)
14
+ if (property.minCount > 0) {
15
+ if (isIRI) {
16
+ // For IRI properties, value is an object or array of objects
17
+ const isEmpty = value === undefined ||
18
+ value === null ||
19
+ (Array.isArray(value) && value.length === 0);
20
+ if (isEmpty)
21
+ return 'At least one selection is required';
22
+ }
23
+ else {
24
+ if (value === undefined || value === null || value === '') {
25
+ return 'This field is required';
26
+ }
27
+ }
28
+ }
29
+ // Skip further validation if value is empty (optional fields)
30
+ if (value === undefined || value === null || value === '')
31
+ return '';
32
+ // sh:in — value must be in the allowed set
33
+ const choices = enumOptions(property);
34
+ if (choices.length > 0) {
35
+ if (isIRI) {
36
+ const selected = Array.isArray(value) ? value : [value];
37
+ const allowedIds = new Set(choices.map((v) => v.id));
38
+ const invalid = selected.find((s) => !allowedIds.has(s.id));
39
+ if (invalid)
40
+ return 'Must be one of the allowed values';
41
+ }
42
+ else {
43
+ const allowedIds = new Set(choices.map((v) => v.id));
44
+ if (!allowedIds.has(String(value))) {
45
+ return 'Must be one of the allowed values';
46
+ }
47
+ }
48
+ }
49
+ // Literal-only constraints
50
+ if (nodeKind === shacl.Literal.id) {
51
+ const strVal = typeof value === 'string' ? value : String(value);
52
+ // sh:pattern
53
+ if (property.pattern) {
54
+ try {
55
+ const re = new RegExp(property.pattern);
56
+ if (!re.test(strVal))
57
+ return 'Value must match the required format';
58
+ }
59
+ catch (_b) {
60
+ // Invalid regex in shape definition — skip
61
+ }
62
+ }
63
+ // sh:minLength
64
+ if (property.minLength != null && strVal.length < property.minLength) {
65
+ return `Must be at least ${property.minLength} characters`;
66
+ }
67
+ // sh:maxLength
68
+ if (property.maxLength != null && strVal.length > property.maxLength) {
69
+ return `Must be at most ${property.maxLength} characters`;
70
+ }
71
+ // Numeric range constraints
72
+ const numVal = typeof value === 'number' ? value : parseFloat(strVal);
73
+ if (!isNaN(numVal)) {
74
+ if (property.minInclusive != null && numVal < Number(property.minInclusive)) {
75
+ return `Must be at least ${property.minInclusive}`;
76
+ }
77
+ if (property.maxInclusive != null && numVal > Number(property.maxInclusive)) {
78
+ return `Must be at most ${property.maxInclusive}`;
79
+ }
80
+ if (property.minExclusive != null && numVal <= Number(property.minExclusive)) {
81
+ return `Must be greater than ${property.minExclusive}`;
82
+ }
83
+ if (property.maxExclusive != null && numVal >= Number(property.maxExclusive)) {
84
+ return `Must be less than ${property.maxExclusive}`;
85
+ }
86
+ }
87
+ }
88
+ return '';
89
+ }
90
+ /**
91
+ * Validate all fields at once (for submit-time gate).
92
+ * Returns an array of errors; empty array means all valid.
93
+ */
94
+ export function validateAllFields(properties, data) {
95
+ const errors = [];
96
+ for (const prop of properties) {
97
+ if (!prop.nodeKind)
98
+ continue; // skip incomplete shapes
99
+ const msg = validateField(prop, data[prop.label]);
100
+ if (msg) {
101
+ errors.push({ propertyLabel: prop.label, message: msg });
102
+ }
103
+ }
104
+ return errors;
105
+ }
106
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/shape/validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /*
2
+ * The few tokens the data manager still defines itself.
3
+ *
4
+ * It used to be 67. Measuring them against `@_linked/css` showed almost all were either
5
+ * Tailwind primitives the theme already assumes, or re-namings of tokens the theme has
6
+ * under better names — `--card-*` is `--surface-*`, `--input-*` is `--field-*`,
7
+ * `--z-tooltip` is `--layer-tooltip`, `--typography-xs-size` is `--text-xs`. Those were
8
+ * renamed in the components rather than shipped here. The families that were genuinely
9
+ * missing went into the theme instead of here: `--intent-*` and `--table-*`
10
+ * (linked-cm/css#11), and the named `--space-*` scale (linked-cm/css#12) that a CSS module
11
+ * needs because Tailwind's `--spacing()` is a compile-time function and cannot resolve in a
12
+ * stylesheet compiled on its own.
13
+ *
14
+ * What is left is genuinely local: pagination has no counterpart in the theme's component
15
+ * families. Values come from Create Now's light theme so the two do not drift on day one.
16
+ * Import before your own theme; anything you define afterwards wins.
17
+ */
18
+
19
+ :root {
20
+ --pagination-button-border: var(--color-gray-200);
21
+ --pagination-button-hover-border: var(--color-tertiary-500);
22
+ --pagination-button-hover-text: var(--color-tertiary-500);
23
+ --pagination-text: var(--color-gray-500);
24
+ --pagination-text-bold: var(--color-gray-900);
25
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * CSS modules, for the compiler.
3
+ *
4
+ * `tsc` only COPIES these into `lib` (see `copy-to-lib`); the class-name hashing and scoping is
5
+ * the consuming bundler's job, as in `@_linked/primitives`. A consumer therefore needs a
6
+ * bundler that understands CSS modules — which any app rendering these components already has.
7
+ *
8
+ * The binding is called `styles`, not `classes`, on purpose. `@_linked/primitives` declares the
9
+ * same ambient module, and inside this workspace its *source* is symlinked, so both
10
+ * declarations are visible and `const classes` in each is a duplicate identifier. Ambient
11
+ * module declarations merge; the names inside them must not collide. Renaming is the whole fix.
12
+ *
13
+ * The declaration cannot simply be dropped either: primitives' version reaches us only through
14
+ * the workspace symlink, so a clean `npm ci` in CI has no declaration at all and every
15
+ * `import style from './X.module.css'` fails.
16
+ */
17
+ declare module '*.module.css' {
18
+ const styles: {
19
+ readonly [key: string]: string;
20
+ };
21
+ export default styles;
22
+ }
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Creating and updating instances, through the Linked Query DSL.
3
+ *
4
+ * The counterpart of `search.ts`, and the last piece of the read/write pair that still
5
+ * went through a control-plane RPC. `Project.createShapeInstance(projectId, …)` needed a
6
+ * project id for three things, none of which require one on the client:
7
+ *
8
+ * - finding the shape → the host already resolved the catalog
9
+ * - minting the new IRI → `host.dataRoot`, a plain value the host supplies
10
+ * - recording a projection edit → a Create Now studio concern, not a write concern
11
+ *
12
+ * So the write names no project either, and `LinkedStorage` routes it exactly as it routes
13
+ * the read: `AppDataRouter` inside Create Now, the app's own dataset in a standalone or
14
+ * Capacitor build. That matters beyond tidiness — a read that routes one way and a write
15
+ * that routes another is how a form silently saves into the wrong dataset.
16
+ */
17
+ import type { NodeShapeWire } from '@_linked/core/shapes/nodeShapeWire';
18
+ /** A form's values, keyed by property label. */
19
+ export type InstanceValues = Record<string, unknown>;
20
+ /**
21
+ * Mint an IRI for a new instance.
22
+ *
23
+ * `dataRoot` is the one value in this path the host has to supply: Create Now takes it
24
+ * from the project's config, a standalone app knows its own domain. Without it there is
25
+ * no namespace to mint into, so this throws rather than inventing one — a node created
26
+ * under a guessed IRI is worse than a failed create.
27
+ */
28
+ export declare function mintInstanceIri(shape: NodeShapeWire, dataRoot?: string): string;
29
+ /**
30
+ * Create one instance and return its IRI.
31
+ *
32
+ * Empty values are dropped rather than written: on a create there is nothing to clear, and
33
+ * an empty literal is a real triple with an empty string in it.
34
+ */
35
+ export declare function createInstanceWithDsl(shape: NodeShapeWire, values: InstanceValues, options?: {
36
+ dataRoot?: string;
37
+ id?: string;
38
+ }): Promise<{
39
+ id: string;
40
+ }>;
41
+ /**
42
+ * Update one instance.
43
+ *
44
+ * Empty becomes `null`, which is how the DSL clears a property — the opposite of create,
45
+ * where the same value is dropped. Both are right: clearing a field the viewer emptied is
46
+ * the whole point of an edit form, and there is nothing to clear on a node that does not
47
+ * exist yet.
48
+ *
49
+ * A payload with nothing recognisable in it is a no-op rather than an empty mutation.
50
+ */
51
+ export declare function updateInstanceWithDsl(shape: NodeShapeWire, instanceId: string, values: InstanceValues): Promise<void>;
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Creating and updating instances, through the Linked Query DSL.
3
+ *
4
+ * The counterpart of `search.ts`, and the last piece of the read/write pair that still
5
+ * went through a control-plane RPC. `Project.createShapeInstance(projectId, …)` needed a
6
+ * project id for three things, none of which require one on the client:
7
+ *
8
+ * - finding the shape → the host already resolved the catalog
9
+ * - minting the new IRI → `host.dataRoot`, a plain value the host supplies
10
+ * - recording a projection edit → a Create Now studio concern, not a write concern
11
+ *
12
+ * So the write names no project either, and `LinkedStorage` routes it exactly as it routes
13
+ * the read: `AppDataRouter` inside Create Now, the app's own dataset in a standalone or
14
+ * Capacitor build. That matters beyond tidiness — a read that routes one way and a write
15
+ * that routes another is how a form silently saves into the wrong dataset.
16
+ */
17
+ import { CreateBuilder } from '@_linked/core/queries/CreateBuilder';
18
+ import { UpdateBuilder } from '@_linked/core/queries/UpdateBuilder';
19
+ /**
20
+ * Strip a value down to what the graph should hold.
21
+ *
22
+ * A relation field carries `{id, label}` — the label is there so a draft can show a name
23
+ * without re-reading the instance. It is display state, not a fact about the node, and
24
+ * writing it would put a second, immediately stale copy of the label in the graph.
25
+ */
26
+ function toGraphValue(value) {
27
+ if (Array.isArray(value))
28
+ return value.map(toGraphValue);
29
+ if (value && typeof value === 'object' && 'id' in value) {
30
+ return { id: value.id };
31
+ }
32
+ return value;
33
+ }
34
+ /** Labels the shape actually declares. Anything else is a stale form field. */
35
+ function knownLabels(shape) {
36
+ var _a;
37
+ return new Set(((_a = shape.propertyShapes) !== null && _a !== void 0 ? _a : []).map((p) => p.label).filter(Boolean));
38
+ }
39
+ /**
40
+ * Mint an IRI for a new instance.
41
+ *
42
+ * `dataRoot` is the one value in this path the host has to supply: Create Now takes it
43
+ * from the project's config, a standalone app knows its own domain. Without it there is
44
+ * no namespace to mint into, so this throws rather than inventing one — a node created
45
+ * under a guessed IRI is worse than a failed create.
46
+ */
47
+ export function mintInstanceIri(shape, dataRoot) {
48
+ if (!dataRoot) {
49
+ throw new Error('Cannot create an instance without `dataRoot`: there is no namespace to mint the ' +
50
+ 'IRI into. Supply it from the host.');
51
+ }
52
+ const segment = (shape.label || 'instance').toLowerCase();
53
+ const base = dataRoot.replace(/\/+$/, '');
54
+ return `${base}/${segment}/${crypto.randomUUID()}`;
55
+ }
56
+ /**
57
+ * Create one instance and return its IRI.
58
+ *
59
+ * Empty values are dropped rather than written: on a create there is nothing to clear, and
60
+ * an empty literal is a real triple with an empty string in it.
61
+ */
62
+ export async function createInstanceWithDsl(shape, values, options = {}) {
63
+ var _a;
64
+ const known = knownLabels(shape);
65
+ const data = {};
66
+ for (const [label, value] of Object.entries(values)) {
67
+ if (value === undefined || value === null || value === '')
68
+ continue;
69
+ if (!known.has(label))
70
+ continue;
71
+ data[label] = toGraphValue(value);
72
+ }
73
+ const id = (_a = options.id) !== null && _a !== void 0 ? _a : mintInstanceIri(shape, options.dataRoot);
74
+ await CreateBuilder.from(shape.id).withId(id).set(data).exec();
75
+ return { id };
76
+ }
77
+ /**
78
+ * Update one instance.
79
+ *
80
+ * Empty becomes `null`, which is how the DSL clears a property — the opposite of create,
81
+ * where the same value is dropped. Both are right: clearing a field the viewer emptied is
82
+ * the whole point of an edit form, and there is nothing to clear on a node that does not
83
+ * exist yet.
84
+ *
85
+ * A payload with nothing recognisable in it is a no-op rather than an empty mutation.
86
+ */
87
+ export async function updateInstanceWithDsl(shape, instanceId, values) {
88
+ const known = knownLabels(shape);
89
+ const data = {};
90
+ for (const [label, value] of Object.entries(values)) {
91
+ if (!known.has(label))
92
+ continue;
93
+ data[label] = value === '' || value === undefined ? null : toGraphValue(value);
94
+ }
95
+ if (Object.keys(data).length === 0)
96
+ return;
97
+ await UpdateBuilder.from(shape.id).for(instanceId).set(data).exec();
98
+ }
99
+ //# sourceMappingURL=write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/write.ts"],"names":[],"mappings":"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"}