@happyvertical/smrt-manufacturing 0.53.3 → 0.53.5

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 (72) hide show
  1. package/AGENTS.md +45 -6
  2. package/README.md +161 -3
  3. package/dist/collections/AssemblyCollection.d.ts +15 -0
  4. package/dist/collections/AssemblyCollection.d.ts.map +1 -0
  5. package/dist/collections/OperationCollection.d.ts +20 -0
  6. package/dist/collections/OperationCollection.d.ts.map +1 -0
  7. package/dist/collections/RoutingStepCollection.d.ts +15 -0
  8. package/dist/collections/RoutingStepCollection.d.ts.map +1 -0
  9. package/dist/collections/index.d.ts +3 -0
  10. package/dist/collections/index.d.ts.map +1 -1
  11. package/dist/index.d.ts +13 -3
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +756 -29
  14. package/dist/index.js.map +1 -1
  15. package/dist/manifest.json +1248 -128
  16. package/dist/models/Assembly.d.ts +62 -0
  17. package/dist/models/Assembly.d.ts.map +1 -0
  18. package/dist/models/BillOfMaterials.d.ts +12 -4
  19. package/dist/models/BillOfMaterials.d.ts.map +1 -1
  20. package/dist/models/BomLine.d.ts +11 -5
  21. package/dist/models/BomLine.d.ts.map +1 -1
  22. package/dist/models/Operation.d.ts +59 -0
  23. package/dist/models/Operation.d.ts.map +1 -0
  24. package/dist/models/RoutingStep.d.ts +46 -0
  25. package/dist/models/RoutingStep.d.ts.map +1 -0
  26. package/dist/models/index.d.ts +3 -0
  27. package/dist/models/index.d.ts.map +1 -1
  28. package/dist/operation-types.d.ts +99 -0
  29. package/dist/operation-types.d.ts.map +1 -0
  30. package/dist/services/AssemblyService.d.ts +217 -0
  31. package/dist/services/AssemblyService.d.ts.map +1 -0
  32. package/dist/services/BomService.d.ts +25 -1
  33. package/dist/services/BomService.d.ts.map +1 -1
  34. package/dist/services/OperationService.d.ts +48 -0
  35. package/dist/services/OperationService.d.ts.map +1 -0
  36. package/dist/services/RoutingService.d.ts +50 -0
  37. package/dist/services/RoutingService.d.ts.map +1 -0
  38. package/dist/services/index.d.ts +3 -0
  39. package/dist/services/index.d.ts.map +1 -1
  40. package/dist/smrt-knowledge.json +1138 -81
  41. package/dist/svelte/components/AssemblyForm.svelte +69 -0
  42. package/dist/svelte/components/AssemblyForm.svelte.d.ts +38 -0
  43. package/dist/svelte/components/AssemblyForm.svelte.d.ts.map +1 -0
  44. package/dist/svelte/components/AssemblyList.svelte +229 -0
  45. package/dist/svelte/components/AssemblyList.svelte.d.ts +28 -0
  46. package/dist/svelte/components/AssemblyList.svelte.d.ts.map +1 -0
  47. package/dist/svelte/components/BomEditor.svelte +575 -0
  48. package/dist/svelte/components/BomEditor.svelte.d.ts +29 -0
  49. package/dist/svelte/components/BomEditor.svelte.d.ts.map +1 -0
  50. package/dist/svelte/components/BomStructureTree.svelte +164 -0
  51. package/dist/svelte/components/BomStructureTree.svelte.d.ts +16 -0
  52. package/dist/svelte/components/BomStructureTree.svelte.d.ts.map +1 -0
  53. package/dist/svelte/components/OperationForm.svelte +258 -0
  54. package/dist/svelte/components/OperationForm.svelte.d.ts +17 -0
  55. package/dist/svelte/components/OperationForm.svelte.d.ts.map +1 -0
  56. package/dist/svelte/components/OperationList.svelte +170 -0
  57. package/dist/svelte/components/OperationList.svelte.d.ts +17 -0
  58. package/dist/svelte/components/OperationList.svelte.d.ts.map +1 -0
  59. package/dist/svelte/i18n.d.ts +87 -0
  60. package/dist/svelte/i18n.d.ts.map +1 -0
  61. package/dist/svelte/i18n.js +87 -0
  62. package/dist/svelte/index.d.ts +28 -0
  63. package/dist/svelte/index.d.ts.map +1 -0
  64. package/dist/svelte/index.js +29 -0
  65. package/dist/svelte/types.d.ts +170 -0
  66. package/dist/svelte/types.d.ts.map +1 -0
  67. package/dist/svelte/types.js +126 -0
  68. package/dist/ui.d.ts +17 -0
  69. package/dist/ui.d.ts.map +1 -0
  70. package/dist/ui.js +72 -0
  71. package/dist/ui.js.map +1 -0
  72. package/package.json +39 -10
@@ -0,0 +1,69 @@
1
+ <script lang="ts">
2
+ /**
3
+ * AssemblyForm — the create and edit form for an assembly, rendered by
4
+ * smrt-fields `ObjectForm` for `@happyvertical/smrt-manufacturing:Assembly`.
5
+ *
6
+ * The fields, their order, labels, help and visibility come from the
7
+ * generated Assembly definition and the consumer's resolved field policy, so
8
+ * a field the policy hides (price, for someone who may not see it) is not
9
+ * rendered. Pass `fields` and `policy` directly, or omit both beneath an
10
+ * `ObjectFormSourceProvider` that knows the Assembly definition.
11
+ *
12
+ * Presentational: the host owns the record and persistence. `onsubmit`
13
+ * should save through the Assembly REST route or `AssemblyCollection` and
14
+ * resolve `true` once the record is stored.
15
+ */
16
+
17
+ import {
18
+ ObjectForm,
19
+ type ObjectFormProps,
20
+ type ResolvedObjectFieldPolicy,
21
+ } from '@happyvertical/smrt-fields/svelte';
22
+ import type { Snippet } from 'svelte';
23
+
24
+ /** The canonical object reference ObjectForm and field policy use for Assembly. */
25
+ const ASSEMBLY_OBJECT_REF = '@happyvertical/smrt-manufacturing:Assembly';
26
+
27
+ export interface AssemblyFormProps {
28
+ /** Generated browser-safe Assembly field definitions; pass with `policy`. */
29
+ fields?: ObjectFormProps['fields'];
30
+ /** The resolved field policy for Assembly; pass with `fields`. */
31
+ policy?: ResolvedObjectFieldPolicy;
32
+ /** The record being created or edited. Bind it to keep values in the host. */
33
+ value?: Record<string, unknown>;
34
+ /** True for a new assembly (policy defaults may prefill), false for an edit. */
35
+ isNewRecord?: boolean;
36
+ /** Blocks input and submission while the host saves. */
37
+ disabled?: boolean;
38
+ /** Shows the basic/advanced field toggle. */
39
+ showModeSwitch?: boolean;
40
+ /** Controls rendered after the fields, inside the form (e.g. a cancel button). */
41
+ actions?: Snippet;
42
+ /** Saves the record; resolve `true` only once it is stored. */
43
+ onsubmit?: ObjectFormProps['onsubmit'];
44
+ }
45
+
46
+ let {
47
+ fields,
48
+ policy,
49
+ value = $bindable<Record<string, unknown>>({}),
50
+ isNewRecord = true,
51
+ disabled = false,
52
+ showModeSwitch = true,
53
+ actions,
54
+ onsubmit,
55
+ }: AssemblyFormProps = $props();
56
+ </script>
57
+
58
+ <ObjectForm
59
+ objectRef={ASSEMBLY_OBJECT_REF}
60
+ {fields}
61
+ {policy}
62
+ bind:value
63
+ {isNewRecord}
64
+ {disabled}
65
+ {showModeSwitch}
66
+ {actions}
67
+ {onsubmit}
68
+ class="assembly-form"
69
+ />
@@ -0,0 +1,38 @@
1
+ /**
2
+ * AssemblyForm — the create and edit form for an assembly, rendered by
3
+ * smrt-fields `ObjectForm` for `@happyvertical/smrt-manufacturing:Assembly`.
4
+ *
5
+ * The fields, their order, labels, help and visibility come from the
6
+ * generated Assembly definition and the consumer's resolved field policy, so
7
+ * a field the policy hides (price, for someone who may not see it) is not
8
+ * rendered. Pass `fields` and `policy` directly, or omit both beneath an
9
+ * `ObjectFormSourceProvider` that knows the Assembly definition.
10
+ *
11
+ * Presentational: the host owns the record and persistence. `onsubmit`
12
+ * should save through the Assembly REST route or `AssemblyCollection` and
13
+ * resolve `true` once the record is stored.
14
+ */
15
+ import { type ObjectFormProps, type ResolvedObjectFieldPolicy } from '@happyvertical/smrt-fields/svelte';
16
+ import type { Snippet } from 'svelte';
17
+ export interface AssemblyFormProps {
18
+ /** Generated browser-safe Assembly field definitions; pass with `policy`. */
19
+ fields?: ObjectFormProps['fields'];
20
+ /** The resolved field policy for Assembly; pass with `fields`. */
21
+ policy?: ResolvedObjectFieldPolicy;
22
+ /** The record being created or edited. Bind it to keep values in the host. */
23
+ value?: Record<string, unknown>;
24
+ /** True for a new assembly (policy defaults may prefill), false for an edit. */
25
+ isNewRecord?: boolean;
26
+ /** Blocks input and submission while the host saves. */
27
+ disabled?: boolean;
28
+ /** Shows the basic/advanced field toggle. */
29
+ showModeSwitch?: boolean;
30
+ /** Controls rendered after the fields, inside the form (e.g. a cancel button). */
31
+ actions?: Snippet;
32
+ /** Saves the record; resolve `true` only once it is stored. */
33
+ onsubmit?: ObjectFormProps['onsubmit'];
34
+ }
35
+ declare const AssemblyForm: import("svelte").Component<AssemblyFormProps, {}, "value">;
36
+ type AssemblyForm = ReturnType<typeof AssemblyForm>;
37
+ export default AssemblyForm;
38
+ //# sourceMappingURL=AssemblyForm.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssemblyForm.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/AssemblyForm.svelte.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,yBAAyB,EAC/B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGtC,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,MAAM,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC;IACnC,kEAAkE;IAClE,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,gFAAgF;IAChF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;CACxC;AA2BD,QAAA,MAAM,YAAY,4DAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
@@ -0,0 +1,229 @@
1
+ <script lang="ts">
2
+ /**
3
+ * AssemblyList — a table of assemblies: name, part reference, SKU codes,
4
+ * price, labour estimate and the version of the active bill. Presentational:
5
+ * the host loads assemblies, their SKUs and active bills, and adapts each row
6
+ * with `toAssemblyView`.
7
+ *
8
+ * Pass the resolved field `policy` for `@happyvertical/smrt-manufacturing:Assembly`
9
+ * to apply the consumer's field policy: a field the policy hides (price, for
10
+ * a viewer who may not see it) drops its column.
11
+ */
12
+
13
+ import {
14
+ policyToVisibleColumnIds,
15
+ type ResolvedObjectFieldPolicy,
16
+ } from '@happyvertical/smrt-fields/svelte';
17
+ import { Button, CurrencyDisplay } from '@happyvertical/smrt-ui';
18
+ import { useI18n } from '@happyvertical/smrt-ui/i18n';
19
+ import { M } from '../i18n.js';
20
+ import { type AssemblyView, splitLabourMinutes } from '../types.js';
21
+
22
+ const { t } = useI18n();
23
+
24
+ export interface AssemblyListProps {
25
+ /** Assemblies to show, in the host's order. */
26
+ assemblies: AssemblyView[];
27
+ /** The resolved field policy for Assembly; hidden fields drop their column. */
28
+ policy?: ResolvedObjectFieldPolicy;
29
+ /** ISO 4217 currency of the prices. */
30
+ currency?: string;
31
+ /** Invoked with the assembly id when a name is activated. */
32
+ onselect?: (id: string) => void;
33
+ /** Message shown when there are no assemblies. */
34
+ emptyMessage?: string;
35
+ }
36
+
37
+ const {
38
+ assemblies,
39
+ policy,
40
+ currency = 'USD',
41
+ onselect,
42
+ emptyMessage,
43
+ }: AssemblyListProps = $props();
44
+
45
+ // Columns that map to Assembly fields follow the policy; SKU and bill are
46
+ // computed from neighbours and always show. When the policy hides the name,
47
+ // the row header falls back to the SKU codes, then the part reference.
48
+ const POLICY_COLUMNS = [
49
+ { id: 'name' },
50
+ { id: 'partReference' },
51
+ { id: 'sku' },
52
+ { id: 'price' },
53
+ { id: 'labour' },
54
+ { id: 'bill' },
55
+ ];
56
+ const FIELD_BY_COLUMN = { labour: 'estimatedLabourMinutes' };
57
+
58
+ const visible = $derived(
59
+ policy
60
+ ? policyToVisibleColumnIds(policy, POLICY_COLUMNS, FIELD_BY_COLUMN)
61
+ : new Set(POLICY_COLUMNS.map((column) => column.id)),
62
+ );
63
+
64
+ /** The row header: the name, or a visible identifier when the name is hidden. */
65
+ function rowLabel(assembly: AssemblyView): string {
66
+ if (visible.has('name')) return assembly.name;
67
+ if (assembly.skuCodes.length > 0) return assembly.skuCodes.join(', ');
68
+ if (visible.has('partReference') && assembly.partReference)
69
+ return assembly.partReference;
70
+ return t(M['manufacturing.assembly_list.unnamed']);
71
+ }
72
+
73
+ function labour(minutes: number): string {
74
+ if (!minutes || minutes <= 0)
75
+ return t(M['manufacturing.labour.not_estimated']);
76
+ const split = splitLabourMinutes(minutes);
77
+ return split.hours === 0
78
+ ? t(M['manufacturing.labour.minutes'], { minutes: split.minutes })
79
+ : t(M['manufacturing.labour.hours_minutes'], split);
80
+ }
81
+ </script>
82
+
83
+ {#if assemblies.length === 0}
84
+ <p class="assembly-list-empty">
85
+ {emptyMessage ?? t(M['manufacturing.assembly_list.empty'])}
86
+ </p>
87
+ {:else}
88
+ <div class="assembly-list-scroll">
89
+ <table class="assembly-list">
90
+ <caption class="assembly-list-caption">{t(M['manufacturing.assembly_list.caption'])}</caption>
91
+ <thead>
92
+ <tr>
93
+ <th scope="col">
94
+ {t(
95
+ visible.has('name')
96
+ ? M['manufacturing.assembly_list.name']
97
+ : M['manufacturing.assembly_list.assembly'],
98
+ )}
99
+ </th>
100
+ {#if visible.has('partReference')}
101
+ <th scope="col">{t(M['manufacturing.assembly_list.part_reference'])}</th>
102
+ {/if}
103
+ {#if visible.has('sku')}
104
+ <th scope="col">{t(M['manufacturing.assembly_list.sku'])}</th>
105
+ {/if}
106
+ {#if visible.has('price')}
107
+ <th scope="col" class="numeric">{t(M['manufacturing.assembly_list.price'])}</th>
108
+ {/if}
109
+ {#if visible.has('labour')}
110
+ <th scope="col" class="numeric">{t(M['manufacturing.assembly_list.labour'])}</th>
111
+ {/if}
112
+ {#if visible.has('bill')}
113
+ <th scope="col">{t(M['manufacturing.assembly_list.bill'])}</th>
114
+ {/if}
115
+ </tr>
116
+ </thead>
117
+ <tbody>
118
+ {#each assemblies as assembly (assembly.id)}
119
+ <tr>
120
+ <th scope="row" class="assembly-list-name">
121
+ {#if onselect}
122
+ <Button
123
+ variant="ghost"
124
+ size="sm"
125
+ onclick={() => onselect(assembly.id)}
126
+ aria-label={t(M['manufacturing.assembly_list.select_aria'], { name: rowLabel(assembly) })}
127
+ >
128
+ {rowLabel(assembly)}
129
+ </Button>
130
+ {:else}
131
+ {rowLabel(assembly)}
132
+ {/if}
133
+ </th>
134
+ {#if visible.has('partReference')}
135
+ <td>
136
+ {#if assembly.partReference}
137
+ {assembly.partReference}
138
+ {:else}
139
+ <span class="assembly-list-none">{t(M['manufacturing.assembly_list.none'])}</span>
140
+ {/if}
141
+ </td>
142
+ {/if}
143
+ {#if visible.has('sku')}
144
+ <td class="assembly-list-code">
145
+ {#if assembly.skuCodes.length > 0}
146
+ {assembly.skuCodes.join(', ')}
147
+ {:else}
148
+ <span class="assembly-list-none">{t(M['manufacturing.assembly_list.none'])}</span>
149
+ {/if}
150
+ </td>
151
+ {/if}
152
+ {#if visible.has('price')}
153
+ <td class="numeric">
154
+ <CurrencyDisplay amount={assembly.price} {currency} unit="cents" size="sm" />
155
+ </td>
156
+ {/if}
157
+ {#if visible.has('labour')}
158
+ <td class="numeric">{labour(assembly.estimatedLabourMinutes)}</td>
159
+ {/if}
160
+ {#if visible.has('bill')}
161
+ <td>
162
+ {#if assembly.activeBomVersion !== null}
163
+ {t(M['manufacturing.assembly_list.bill_active'], { version: assembly.activeBomVersion })}
164
+ {:else}
165
+ <span class="assembly-list-none">{t(M['manufacturing.assembly_list.bill_missing'])}</span>
166
+ {/if}
167
+ </td>
168
+ {/if}
169
+ </tr>
170
+ {/each}
171
+ </tbody>
172
+ </table>
173
+ </div>
174
+ {/if}
175
+
176
+ <style>
177
+ .assembly-list-scroll {
178
+ overflow-x: auto;
179
+ }
180
+
181
+ .assembly-list {
182
+ width: 100%;
183
+ border-collapse: collapse;
184
+ }
185
+
186
+ .assembly-list-caption {
187
+ position: absolute;
188
+ width: 1px;
189
+ height: 1px;
190
+ overflow: hidden;
191
+ clip-path: inset(50%);
192
+ white-space: nowrap;
193
+ }
194
+
195
+ .assembly-list th,
196
+ .assembly-list td {
197
+ padding: 0.5rem 0.75rem;
198
+ text-align: left;
199
+ border-bottom: 1px solid var(--smrt-color-outline-variant, transparent);
200
+ }
201
+
202
+ .assembly-list thead th {
203
+ font-size: var(--smrt-typography-label-medium-size, 0.75rem);
204
+ font-weight: var(--smrt-typography-label-medium-weight, 500);
205
+ color: var(--smrt-color-on-surface-variant, inherit);
206
+ }
207
+
208
+ .assembly-list .numeric {
209
+ text-align: right;
210
+ font-variant-numeric: tabular-nums;
211
+ }
212
+
213
+ .assembly-list-name {
214
+ font-weight: var(--smrt-typography-title-small-weight, 500);
215
+ }
216
+
217
+ .assembly-list-code {
218
+ font-variant-numeric: tabular-nums;
219
+ }
220
+
221
+ .assembly-list-none,
222
+ .assembly-list-empty {
223
+ color: var(--smrt-color-on-surface-variant, inherit);
224
+ }
225
+
226
+ .assembly-list-empty {
227
+ padding: 1rem 0;
228
+ }
229
+ </style>
@@ -0,0 +1,28 @@
1
+ /**
2
+ * AssemblyList — a table of assemblies: name, part reference, SKU codes,
3
+ * price, labour estimate and the version of the active bill. Presentational:
4
+ * the host loads assemblies, their SKUs and active bills, and adapts each row
5
+ * with `toAssemblyView`.
6
+ *
7
+ * Pass the resolved field `policy` for `@happyvertical/smrt-manufacturing:Assembly`
8
+ * to apply the consumer's field policy: a field the policy hides (price, for
9
+ * a viewer who may not see it) drops its column.
10
+ */
11
+ import { type ResolvedObjectFieldPolicy } from '@happyvertical/smrt-fields/svelte';
12
+ import { type AssemblyView } from '../types.js';
13
+ export interface AssemblyListProps {
14
+ /** Assemblies to show, in the host's order. */
15
+ assemblies: AssemblyView[];
16
+ /** The resolved field policy for Assembly; hidden fields drop their column. */
17
+ policy?: ResolvedObjectFieldPolicy;
18
+ /** ISO 4217 currency of the prices. */
19
+ currency?: string;
20
+ /** Invoked with the assembly id when a name is activated. */
21
+ onselect?: (id: string) => void;
22
+ /** Message shown when there are no assemblies. */
23
+ emptyMessage?: string;
24
+ }
25
+ declare const AssemblyList: import("svelte").Component<AssemblyListProps, {}, "">;
26
+ type AssemblyList = ReturnType<typeof AssemblyList>;
27
+ export default AssemblyList;
28
+ //# sourceMappingURL=AssemblyList.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssemblyList.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/AssemblyList.svelte.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,mCAAmC,CAAC;AAI3C,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,aAAa,CAAC;AAGpE,MAAM,WAAW,iBAAiB;IAChC,+CAA+C;IAC/C,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,+EAA+E;IAC/E,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAuJD,QAAA,MAAM,YAAY,uDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}