@happyvertical/smrt-products 0.55.19 → 0.55.22

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 (27) hide show
  1. package/dist/lib/chunks/{__smrt-register__-CHWpaPZb.js → __smrt-register__-CdwszHtZ.js} +2 -2
  2. package/dist/lib/chunks/{__smrt-register__-CHWpaPZb.js.map → __smrt-register__-CdwszHtZ.js.map} +1 -1
  3. package/dist/lib/chunks/{collections-OOJeR05d.js → collections-CUwL7Dq6.js} +2 -2
  4. package/dist/lib/chunks/{collections-OOJeR05d.js.map → collections-CUwL7Dq6.js.map} +1 -1
  5. package/dist/lib/chunks/{components-B_eBqqq7.js → components-DMJz1geh.js} +2 -2
  6. package/dist/lib/chunks/components-DMJz1geh.js.map +1 -0
  7. package/dist/lib/chunks/{generated-DEBvTT0O.js → generated-Cwx8YMiS.js} +2 -2
  8. package/dist/lib/chunks/{generated-DEBvTT0O.js.map → generated-Cwx8YMiS.js.map} +1 -1
  9. package/dist/lib/chunks/models-CVqA-k81.js +2 -0
  10. package/dist/lib/collections.js +1 -1
  11. package/dist/lib/components.js +1 -1
  12. package/dist/lib/generated.js +1 -1
  13. package/dist/lib/index.js +5 -5
  14. package/dist/lib/lib/components/LiveProductList.svelte +2 -2
  15. package/dist/lib/lib/components/ProductCard.svelte +3 -3
  16. package/dist/lib/lib/components/ProductForm.svelte +3 -3
  17. package/dist/lib/lib/components/TestComponent.svelte +1 -1
  18. package/dist/lib/lib/components/auto-generated/AutoForm.svelte +3 -3
  19. package/dist/lib/lib/features/CategoryManager.svelte +1 -1
  20. package/dist/lib/lib/features/ProductCatalog.svelte +2 -2
  21. package/dist/lib/manifest.json +1 -1
  22. package/dist/lib/models.js +1 -1
  23. package/dist/lib/smrt-knowledge.json +3 -3
  24. package/dist/lib/smrt-products.css +5 -5
  25. package/package.json +9 -9
  26. package/dist/lib/chunks/components-B_eBqqq7.js.map +0 -1
  27. package/dist/lib/chunks/models-D2FZFimv.js +0 -2
@@ -101,7 +101,7 @@ function ProductCard($$anchor, $$props) {
101
101
  type: "button",
102
102
  variant: "danger",
103
103
  size: "sm",
104
- onclick: () => $$props.onDelete?.($$props.product.id),
104
+ onclick: () => $$props.product.id && $$props.onDelete?.($$props.product.id),
105
105
  children: ($$anchor, $$slotProps) => {
106
106
  $.next();
107
107
  var text_7 = $.text("Delete");
@@ -389,4 +389,4 @@ function ProductForm($$anchor, $$props) {
389
389
  //#endregion
390
390
  export { ProductCard as n, ProductForm as t };
391
391
 
392
- //# sourceMappingURL=components-B_eBqqq7.js.map
392
+ //# sourceMappingURL=components-DMJz1geh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components-DMJz1geh.js","names":[],"sources":["../../../src/lib/components/ProductCard.svelte","../../../src/lib/components/ProductForm.svelte"],"sourcesContent":["<script lang=\"ts\">\nimport { Button } from '@happyvertical/smrt-ui/ui';\nimport type { ProductData } from '../types';\n\ninterface Props {\n /** The product to display. */\n product: ProductData;\n /** Fired when the user clicks to edit the product. */\n onEdit?: (product: ProductData) => void;\n /** Fired when the user clicks to delete the product. */\n onDelete?: (id: string) => void;\n}\n\nconst { product, onEdit, onDelete }: Props = $props();\n</script>\n\n<div class=\"product-card\" data-smrt-component=\"ProductCard\">\n <div class=\"product-header\">\n <h3 class=\"product-name\">{product.name}</h3>\n {#if product.manufacturer}\n <div class=\"product-manufacturer\">{product.manufacturer}</div>\n {/if}\n </div>\n\n {#if product.model}\n <div class=\"product-model\">Model: {product.model}</div>\n {/if}\n\n {#if product.description}\n <p class=\"product-description\">{product.description}</p>\n {/if}\n\n <div class=\"product-meta\">\n {#if product.category}\n <div class=\"product-category\">Category: {product.category}</div>\n {/if}\n \n {#if product.tags && product.tags.length > 0}\n <div class=\"product-tags\">\n {#each product.tags as tag}\n <span class=\"tag\">{tag}</span>\n {/each}\n </div>\n {/if}\n </div>\n \n <div class=\"product-actions\">\n {#if onEdit}\n <Button type=\"button\" variant=\"secondary\" size=\"sm\" onclick={() => onEdit?.(product)}>\n Edit\n </Button>\n {/if}\n\n {#if onDelete}\n <Button type=\"button\" variant=\"danger\" size=\"sm\" onclick={() => product.id && onDelete?.(product.id)}>\n Delete\n </Button>\n {/if}\n </div>\n</div>\n\n<style>\n@layer smrt.reset, smrt.structure, smrt.theme;\n@layer smrt.theme {\n .product-card {\n border: var(--smrt-hairline);\n border-radius: var(--smrt-radius-md);\n padding: 1rem;\n background: var(--smrt-color-surface);\n box-shadow: var(--smrt-elevation-1, 0 1px 3px color-mix(in srgb, var(--smrt-color-shadow) 10%, transparent));\n transition: box-shadow 0.2s;\n }\n\n .product-card:hover {\n box-shadow: var(--smrt-elevation-2, 0 4px 6px color-mix(in srgb, var(--smrt-color-shadow) 10%, transparent));\n }\n \n .product-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 0.5rem;\n }\n \n .product-name {\n margin: 0;\n font-size: var(--smrt-typography-title-medium-size, 1.125rem);\n font-weight: var(--smrt-typography-weight-semibold, 600);\n color: var(--smrt-color-on-surface);\n }\n\n .product-manufacturer {\n font-size: var(--smrt-typography-title-small-size, 0.875rem);\n font-weight: var(--smrt-typography-weight-medium, 500);\n color: var(--smrt-color-on-surface-variant);\n }\n\n .product-model {\n font-size: var(--smrt-typography-body-medium-size, 0.875rem);\n color: var(--smrt-color-on-surface-variant);\n margin-bottom: 0.5rem;\n }\n\n .product-category {\n font-size: var(--smrt-typography-label-medium-size, 0.75rem);\n font-weight: var(--smrt-typography-weight-medium, 500);\n color: var(--smrt-color-on-surface);\n background: var(--smrt-color-surface-container);\n padding: 0.25rem 0.5rem;\n border-radius: var(--smrt-radius-sm);\n display: inline-block;\n margin-bottom: 0.5rem;\n }\n \n .product-description {\n margin: 0.5rem 0;\n color: var(--smrt-color-on-surface-variant);\n font-size: var(--smrt-typography-body-medium-size, 0.875rem);\n line-height: var(--smrt-typography-body-medium-line-height, 1.4);\n }\n \n .product-meta {\n margin: 0.75rem 0;\n }\n \n \n .product-tags {\n margin-top: 0.5rem;\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n }\n \n .tag {\n background: var(--smrt-color-surface-container);\n color: var(--smrt-color-on-surface);\n padding: 0.125rem 0.5rem;\n border-radius: var(--smrt-radius-full);\n font-size: var(--smrt-typography-label-medium-size, 0.75rem);\n }\n\n .product-actions {\n display: flex;\n gap: 0.5rem;\n margin-top: 1rem;\n padding-top: 0.75rem;\n border-top: var(--smrt-hairline);\n }\n}\n</style>","<script lang=\"ts\">\nimport { Form, Input, Textarea } from '@happyvertical/smrt-ui/forms';\nimport { useI18n } from '@happyvertical/smrt-ui/i18n';\nimport { Button } from '@happyvertical/smrt-ui/ui';\nimport { M } from '../i18n.js';\nimport type { ProductData } from '../types';\n\nconst { t } = useI18n();\n\ninterface Props {\n /** Product to populate the form with. */\n product?: Partial<ProductData>;\n /** Fired when the user submits the form. */\n onSubmit: (product: Partial<ProductData>) => void;\n /** Fired when the user clicks the cancel button. */\n onCancel?: () => void;\n /** Disables all inputs and shows \"Saving...\" when true. */\n loading?: boolean;\n}\n\nconst { product = {}, onSubmit, onCancel, loading = false }: Props = $props();\n\nconst formData = $state({\n name: product.name || '',\n description: product.description || '',\n price: product.price || 0,\n inStock: product.inStock ?? true,\n category: product.category || '',\n tags: product.tags?.join(', ') || '',\n});\n\nlet errors = $state<Record<string, string>>({});\n\nfunction validateForm() {\n errors = {};\n\n if (!formData.name.trim()) {\n errors.name = 'Product name is required';\n }\n\n if (formData.price < 0) {\n errors.price = 'Price must be non-negative';\n }\n\n return Object.keys(errors).length === 0;\n}\n\nfunction handleSubmit(event: Event) {\n event.preventDefault();\n\n if (!validateForm()) {\n return;\n }\n\n const productData: Partial<ProductData> = {\n ...product,\n name: formData.name.trim(),\n description: formData.description.trim() || undefined,\n price: formData.price,\n inStock: formData.inStock,\n category: formData.category.trim(),\n tags: formData.tags\n ? formData.tags\n .split(',')\n .map((tag) => tag.trim())\n .filter(Boolean)\n : [],\n };\n\n onSubmit(productData);\n}\n</script>\n\n<div class=\"product-form-shell\" data-smrt-component=\"ProductForm\">\n <Form onsubmit={handleSubmit} class=\"product-form\">\n <div class=\"form-group\">\n <label for=\"name\">{t(M['products.product_form.name_label'])}</label>\n <Input\n id=\"name\"\n type=\"text\"\n bind:value={formData.name}\n disabled={loading}\n class={errors.name ? 'error' : ''}\n placeholder={t(M['products.product_form.name_placeholder'])}\n />\n {#if errors.name}\n <span class=\"error-message\">{errors.name}</span>\n {/if}\n </div>\n\n <div class=\"form-group\">\n <label for=\"description\">Description</label>\n <Textarea\n id=\"description\"\n bind:value={formData.description}\n disabled={loading}\n placeholder={t(M['products.product_form.description_placeholder'])}\n rows={3}\n ></Textarea>\n </div>\n\n <div class=\"form-row\">\n <div class=\"form-group\">\n <label for=\"price\">Price *</label>\n <Input\n id=\"price\"\n type=\"number\"\n step=\"0.01\"\n min=\"0\"\n bind:value={formData.price}\n disabled={loading}\n class={errors.price ? 'error' : ''}\n placeholder=\"0.00\"\n />\n {#if errors.price}\n <span class=\"error-message\">{errors.price}</span>\n {/if}\n </div>\n\n <div class=\"form-group\">\n <label for=\"category\">Category</label>\n <Input\n id=\"category\"\n type=\"text\"\n bind:value={formData.category}\n disabled={loading}\n placeholder={t(M['products.product_form.category_placeholder'])}\n />\n </div>\n </div>\n\n <div class=\"form-group\">\n <label for=\"tags\">Tags</label>\n <Input\n id=\"tags\"\n type=\"text\"\n bind:value={formData.tags}\n disabled={loading}\n placeholder={t(M['products.product_form.tags_placeholder'])}\n />\n <small class=\"form-hint\">{t(M['products.product_form.tags_hint'])}</small>\n </div>\n\n <div class=\"form-group\">\n <label class=\"checkbox-label\">\n <!-- raw-primitive-allow: native checkbox; no Provider-free checkbox primitive (Toggle is a switch with different semantics, CheckboxInput requires a Provider) -->\n <input\n type=\"checkbox\"\n bind:checked={formData.inStock}\n disabled={loading}\n class=\"form-checkbox\"\n />\n {t(M['products.product_form.in_stock_label'])}\n </label>\n </div>\n\n <div class=\"form-actions\">\n {#if onCancel}\n <Button type=\"button\" variant=\"secondary\" onclick={onCancel} disabled={loading}>\n Cancel\n </Button>\n {/if}\n\n <Button type=\"submit\" variant=\"primary\" disabled={loading}>\n {#if loading}\n Saving...\n {:else}\n {product.id ? 'Update Product' : 'Create Product'}\n {/if}\n </Button>\n </div>\n </Form>\n</div>\n\n<style>\n@layer smrt.reset, smrt.structure, smrt.theme;\n@layer smrt.theme {\n .product-form-shell :global(.product-form) {\n max-width: 500px;\n padding: 1.5rem;\n background: var(--smrt-color-surface);\n border-radius: var(--smrt-radius-md);\n border: var(--smrt-hairline);\n }\n\n .form-group {\n margin-bottom: 1rem;\n }\n\n .form-row {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1rem;\n }\n\n label {\n display: block;\n margin-bottom: 0.25rem;\n font-weight: var(--smrt-typography-weight-medium, 500);\n color: var(--smrt-color-on-surface);\n font-size: var(--smrt-typography-label-large-size, 0.875rem);\n }\n\n /* Error border on the migrated <Input>. The primitive renders the inner\n <input class=\"input error\"> inside its own component, so the scoped class\n can't reach it without :global (#1589). */\n .product-form-shell :global([data-smrt-component=\"Input\"].error) {\n border-color: var(--smrt-color-error);\n }\n\n .checkbox-label {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n cursor: pointer;\n }\n \n .form-checkbox {\n width: auto;\n }\n \n .form-hint {\n color: var(--smrt-color-on-surface-variant);\n font-size: var(--smrt-typography-body-small-size, 0.75rem);\n margin-top: 0.25rem;\n }\n\n .error-message {\n color: var(--smrt-color-error);\n font-size: var(--smrt-typography-label-medium-size, 0.75rem);\n margin-top: 0.25rem;\n display: block;\n }\n\n .form-actions {\n display: flex;\n gap: 0.75rem;\n justify-content: flex-end;\n margin-top: 1.5rem;\n padding-top: 1rem;\n border-top: var(--smrt-hairline);\n }\n}\n</style>"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import "./__smrt-register__-CHWpaPZb.js";
1
+ import "./__smrt-register__-CdwszHtZ.js";
2
2
  //#region src/lib/generated/index.ts
3
3
  var autoGeneratedComponents = {};
4
4
  //#endregion
5
5
  export { autoGeneratedComponents as t };
6
6
 
7
- //# sourceMappingURL=generated-DEBvTT0O.js.map
7
+ //# sourceMappingURL=generated-Cwx8YMiS.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"generated-DEBvTT0O.js","names":[],"sources":["../../../src/lib/generated/index.ts"],"sourcesContent":["/**\n * Auto-generated SMRT Components\n *\n * This file is automatically generated by the SMRT Vite plugin.\n * It exports UI components that are auto-generated from @smrt() decorated classes.\n *\n * DO NOT EDIT THIS FILE MANUALLY - it will be overwritten.\n */\n\n// Self-register this package's manifest for consumers that import via this\n// subpath without the main entry. See src/__smrt-register__.ts (issue #1132).\nimport '../../__smrt-register__.js';\n\n// Auto-generated components will be exported here by the SMRT Vite plugin\n// Examples:\n// export { default as SmrtProductForm } from './SmrtProductForm.svelte';\n// export { default as SmrtProductTable } from './SmrtProductTable.svelte';\n// export { default as SmrtCategoryForm } from './SmrtCategoryForm.svelte';\n\n// For now, export an empty object to prevent import errors\nexport const autoGeneratedComponents = {};\n"],"mappings":";;AAoBA,IAAa,0BAA0B,CAAC"}
1
+ {"version":3,"file":"generated-Cwx8YMiS.js","names":[],"sources":["../../../src/lib/generated/index.ts"],"sourcesContent":["/**\n * Auto-generated SMRT Components\n *\n * This file is automatically generated by the SMRT Vite plugin.\n * It exports UI components that are auto-generated from @smrt() decorated classes.\n *\n * DO NOT EDIT THIS FILE MANUALLY - it will be overwritten.\n */\n\n// Self-register this package's manifest for consumers that import via this\n// subpath without the main entry. See src/__smrt-register__.ts (issue #1132).\nimport '../../__smrt-register__.js';\n\n// Auto-generated components will be exported here by the SMRT Vite plugin\n// Examples:\n// export { default as SmrtProductForm } from './SmrtProductForm.svelte';\n// export { default as SmrtProductTable } from './SmrtProductTable.svelte';\n// export { default as SmrtCategoryForm } from './SmrtCategoryForm.svelte';\n\n// For now, export an empty object to prevent import errors\nexport const autoGeneratedComponents = {};\n"],"mappings":";;AAoBA,IAAa,0BAA0B,CAAC"}
@@ -0,0 +1,2 @@
1
+ import "./__smrt-register__-CdwszHtZ.js";
2
+ import "./Sku-CdhhTtjd.js";
@@ -1,4 +1,4 @@
1
- import { i as CategoryCollection, n as ProductVariantCollection, r as MaterialCollection, t as SkuCollection } from "./chunks/collections-OOJeR05d.js";
1
+ import { i as CategoryCollection, n as ProductVariantCollection, r as MaterialCollection, t as SkuCollection } from "./chunks/collections-CUwL7Dq6.js";
2
2
  import { t as ProductCollection } from "./chunks/ProductCollection-BJXVIE6A.js";
3
3
  import { t as ProductAssetCollection } from "./chunks/ProductAssetCollection-pTm67_Vn.js";
4
4
  export { CategoryCollection, MaterialCollection, ProductAssetCollection, ProductCollection, ProductVariantCollection, SkuCollection };
@@ -1,2 +1,2 @@
1
- import { n as ProductCard, t as ProductForm } from "./chunks/components-B_eBqqq7.js";
1
+ import { n as ProductCard, t as ProductForm } from "./chunks/components-DMJz1geh.js";
2
2
  export { ProductCard, ProductForm };
@@ -1,2 +1,2 @@
1
- import { t as autoGeneratedComponents } from "./chunks/generated-DEBvTT0O.js";
1
+ import { t as autoGeneratedComponents } from "./chunks/generated-Cwx8YMiS.js";
2
2
  export { autoGeneratedComponents };
package/dist/lib/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { t as __exportAll } from "./chunks/rolldown-runtime-D7D4PA-g.js";
2
- import "./chunks/__smrt-register__-CHWpaPZb.js";
2
+ import "./chunks/__smrt-register__-CdwszHtZ.js";
3
3
  import { a as Product, i as Material, n as ProductVariant, o as ProductType, r as ProductAsset, s as Category, t as Sku } from "./chunks/Sku-CdhhTtjd.js";
4
- import { i as CategoryCollection, n as ProductVariantCollection, r as MaterialCollection, t as SkuCollection } from "./chunks/collections-OOJeR05d.js";
4
+ import { i as CategoryCollection, n as ProductVariantCollection, r as MaterialCollection, t as SkuCollection } from "./chunks/collections-CUwL7Dq6.js";
5
5
  import { t as ProductCollection } from "./chunks/ProductCollection-BJXVIE6A.js";
6
6
  import { t as ProductAssetCollection } from "./chunks/ProductAssetCollection-pTm67_Vn.js";
7
- import { n as ProductCard, t as ProductForm } from "./chunks/components-B_eBqqq7.js";
8
- import { t as autoGeneratedComponents } from "./chunks/generated-DEBvTT0O.js";
9
- import "./chunks/models-D2FZFimv.js";
7
+ import { n as ProductCard, t as ProductForm } from "./chunks/components-DMJz1geh.js";
8
+ import { t as autoGeneratedComponents } from "./chunks/generated-Cwx8YMiS.js";
9
+ import "./chunks/models-CVqA-k81.js";
10
10
  import { n as productStore, t as ProductStoreClass } from "./chunks/stores-CB0SI1c5.js";
11
11
  import { i as slugify, n as formatPrice, r as generateId, t as formatDate } from "./chunks/utils-BgTqlQoH.js";
12
12
  import { SmrtRecipe, startRestServer } from "@happyvertical/smrt-core";
@@ -118,7 +118,7 @@ async function addProduct() {
118
118
  name="name"
119
119
  bind:value={newName}
120
120
  placeholder={t(M['products.live_list.name_placeholder'])}
121
- aria-label={t(M['products.live_list.name_placeholder'])}
121
+ label={t(M['products.live_list.name_placeholder'])}
122
122
  disabled={submitting}
123
123
  />
124
124
  <Button type="submit" variant="primary" disabled={submitting || !newName.trim()}>
@@ -166,7 +166,7 @@ async function addProduct() {
166
166
  margin: 0 auto;
167
167
  padding: 1.5rem;
168
168
  background: var(--smrt-color-surface);
169
- border: 1px solid var(--smrt-color-outline-variant);
169
+ border: var(--smrt-hairline);
170
170
  border-radius: var(--smrt-radius-md);
171
171
  }
172
172
 
@@ -52,7 +52,7 @@ const { product, onEdit, onDelete }: Props = $props();
52
52
  {/if}
53
53
 
54
54
  {#if onDelete}
55
- <Button type="button" variant="danger" size="sm" onclick={() => onDelete?.(product.id)}>
55
+ <Button type="button" variant="danger" size="sm" onclick={() => product.id && onDelete?.(product.id)}>
56
56
  Delete
57
57
  </Button>
58
58
  {/if}
@@ -63,7 +63,7 @@ const { product, onEdit, onDelete }: Props = $props();
63
63
  @layer smrt.reset, smrt.structure, smrt.theme;
64
64
  @layer smrt.theme {
65
65
  .product-card {
66
- border: 1px solid var(--smrt-color-outline-variant);
66
+ border: var(--smrt-hairline);
67
67
  border-radius: var(--smrt-radius-md);
68
68
  padding: 1rem;
69
69
  background: var(--smrt-color-surface);
@@ -144,7 +144,7 @@ const { product, onEdit, onDelete }: Props = $props();
144
144
  gap: 0.5rem;
145
145
  margin-top: 1rem;
146
146
  padding-top: 0.75rem;
147
- border-top: 1px solid var(--smrt-color-outline-variant);
147
+ border-top: var(--smrt-hairline);
148
148
  }
149
149
  }
150
150
  </style>
@@ -180,7 +180,7 @@ function handleSubmit(event: Event) {
180
180
  padding: 1.5rem;
181
181
  background: var(--smrt-color-surface);
182
182
  border-radius: var(--smrt-radius-md);
183
- border: 1px solid var(--smrt-color-outline-variant);
183
+ border: var(--smrt-hairline);
184
184
  }
185
185
 
186
186
  .form-group {
@@ -204,7 +204,7 @@ function handleSubmit(event: Event) {
204
204
  /* Error border on the migrated <Input>. The primitive renders the inner
205
205
  <input class="input error"> inside its own component, so the scoped class
206
206
  can't reach it without :global (#1589). */
207
- .product-form-shell :global(.input.error) {
207
+ .product-form-shell :global([data-smrt-component="Input"].error) {
208
208
  border-color: var(--smrt-color-error);
209
209
  }
210
210
 
@@ -238,7 +238,7 @@ function handleSubmit(event: Event) {
238
238
  justify-content: flex-end;
239
239
  margin-top: 1.5rem;
240
240
  padding-top: 1rem;
241
- border-top: 1px solid var(--smrt-color-outline-variant);
241
+ border-top: var(--smrt-hairline);
242
242
  }
243
243
  }
244
244
  </style>
@@ -20,7 +20,7 @@ const { t } = useI18n();
20
20
  @layer smrt.theme {
21
21
  .test-component {
22
22
  padding: 1rem;
23
- border: 1px solid var(--smrt-color-outline-variant);
23
+ border: var(--smrt-hairline);
24
24
  border-radius: var(--smrt-radius-sm);
25
25
  background: var(--smrt-color-surface-container-low);
26
26
  }
@@ -125,7 +125,7 @@ function _getFieldType(
125
125
  value={formData[field.name]}
126
126
  label={field.label}
127
127
  placeholder={field.placeholder}
128
- required={field.required || false}
128
+ required={'required' in field && field.required}
129
129
  {readonly}
130
130
  onUpdate={(value) => updateField(field.name, value)}
131
131
  />
@@ -192,7 +192,7 @@ function _getFieldType(
192
192
  gap: 0.75rem;
193
193
  margin-top: 1.5rem;
194
194
  padding-top: 1.5rem;
195
- border-top: 1px solid var(--smrt-color-outline-variant);
195
+ border-top: var(--smrt-hairline);
196
196
  }
197
197
 
198
198
  .form-debug {
@@ -200,7 +200,7 @@ function _getFieldType(
200
200
  padding: 1rem;
201
201
  background: var(--smrt-color-surface-container-low);
202
202
  border-radius: var(--smrt-radius-sm, 0.375rem);
203
- border: 1px solid var(--smrt-color-outline-variant);
203
+ border: var(--smrt-hairline);
204
204
  }
205
205
 
206
206
  .form-debug summary {
@@ -62,7 +62,7 @@ const _loading = $state(false);
62
62
 
63
63
  .placeholder-content {
64
64
  background: var(--smrt-color-surface-container-low);
65
- border: 1px solid var(--smrt-color-outline-variant);
65
+ border: var(--smrt-hairline);
66
66
  border-radius: var(--smrt-radius-md);
67
67
  padding: 2rem;
68
68
  text-align: center;
@@ -172,7 +172,7 @@ function handleCancelForm() {
172
172
  <div class="form-container">
173
173
  <h3>{editingProduct ? 'Edit Product' : 'Create New Product'}</h3>
174
174
  <ProductForm
175
- product={editingProduct}
175
+ product={editingProduct ?? undefined}
176
176
  onSubmit={handleSubmitProduct}
177
177
  onCancel={handleCancelForm}
178
178
  loading={productStore.loading}
@@ -257,7 +257,7 @@ function handleCancelForm() {
257
257
  `.error-state button` rule can't reach the <button> rendered inside the
258
258
  smrt-ui <Button>, so pierce into it with `:global` (#1589); the danger
259
259
  variant already supplies the background/color the old rule set. */
260
- .error-state :global(.button) {
260
+ .error-state :global([data-smrt-component="Button"]) {
261
261
  margin-top: 0.5rem;
262
262
  }
263
263
 
@@ -2,7 +2,7 @@
2
2
  "version": "1.0.0",
3
3
  "timestamp": 0,
4
4
  "packageName": "@happyvertical/smrt-products",
5
- "packageVersion": "0.55.19",
5
+ "packageVersion": "0.55.22",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-products:CategoryCollection": {
8
8
  "name": "categorycollection",
@@ -1,3 +1,3 @@
1
1
  import { a as Product, i as Material, n as ProductVariant, o as ProductType, r as ProductAsset, s as Category, t as Sku } from "./chunks/Sku-CdhhTtjd.js";
2
- import "./chunks/models-D2FZFimv.js";
2
+ import "./chunks/models-CVqA-k81.js";
3
3
  export { Category, Material, Product, ProductAsset, ProductType, ProductVariant, Sku };
@@ -3,12 +3,12 @@
3
3
  "sensitiveFieldsExcluded": true,
4
4
  "generatedAt": "1970-01-01T00:00:00.000Z",
5
5
  "packageName": "@happyvertical/smrt-products",
6
- "packageVersion": "0.55.19",
6
+ "packageVersion": "0.55.22",
7
7
  "sourceManifestPath": "dist/lib/manifest.json",
8
8
  "agentDocPath": "AGENTS.md",
9
9
  "sourceHashes": {
10
- "manifest": "20bee2410cacec39b176a1e628658863c3d55994d7ae317e3716f50c93b407f8",
11
- "packageJson": "214d42afa6a6ad180ffd569f7e9258b593fba049647f45c669ccad88ee4bb891",
10
+ "manifest": "ab018eb1c01d6e758a6e874a308e6d0cac9072df14d7ddaf7f0c3071223e5769",
11
+ "packageJson": "3b23628dd55e373311fd38298d7176b582b0ec3dcd35c96f10ec102c003244ca",
12
12
  "agents": "b5aa86a9c02bb81be5621ae3397ff2dedcef972a520c2ba2f56ee7abf5613b8c"
13
13
  },
14
14
  "exports": [
@@ -2,7 +2,7 @@
2
2
  @layer smrt.reset, smrt.structure, smrt.theme;
3
3
  @layer smrt.theme {
4
4
  .product-card.svelte-11ja2cl {
5
- border: 1px solid var(--smrt-color-outline-variant);
5
+ border: var(--smrt-hairline);
6
6
  border-radius: var(--smrt-radius-md);
7
7
  padding: 1rem;
8
8
  background: var(--smrt-color-surface);
@@ -83,7 +83,7 @@
83
83
  gap: 0.5rem;
84
84
  margin-top: 1rem;
85
85
  padding-top: 0.75rem;
86
- border-top: 1px solid var(--smrt-color-outline-variant);
86
+ border-top: var(--smrt-hairline);
87
87
  }
88
88
  }
89
89
 
@@ -94,7 +94,7 @@
94
94
  padding: 1.5rem;
95
95
  background: var(--smrt-color-surface);
96
96
  border-radius: var(--smrt-radius-md);
97
- border: 1px solid var(--smrt-color-outline-variant);
97
+ border: var(--smrt-hairline);
98
98
  }
99
99
 
100
100
  .form-group.svelte-1hh5ovx {
@@ -118,7 +118,7 @@
118
118
  /* Error border on the migrated <Input>. The primitive renders the inner
119
119
  <input class="input error"> inside its own component, so the scoped class
120
120
  can't reach it without :global (#1589). */
121
- .product-form-shell.svelte-1hh5ovx .input.error {
121
+ .product-form-shell.svelte-1hh5ovx [data-smrt-component="Input"].error {
122
122
  border-color: var(--smrt-color-error);
123
123
  }
124
124
 
@@ -152,7 +152,7 @@
152
152
  justify-content: flex-end;
153
153
  margin-top: 1.5rem;
154
154
  padding-top: 1rem;
155
- border-top: 1px solid var(--smrt-color-outline-variant);
155
+ border-top: var(--smrt-hairline);
156
156
  }
157
157
  }
158
158
  /*$vite$:1*/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-products",
3
- "version": "0.55.19",
3
+ "version": "0.55.22",
4
4
  "smrtJsdoc": "strict",
5
5
  "description": "SMRT products module: triple-purpose microservice template for standalone apps, federated modules, and NPM libraries",
6
6
  "author": "HappyVertical",
@@ -57,13 +57,13 @@
57
57
  "@happyvertical/ai": "^0.103.5",
58
58
  "@happyvertical/files": "^0.103.5",
59
59
  "@happyvertical/logger": "^0.103.5",
60
- "@happyvertical/smrt-assets": "0.55.19",
61
- "@happyvertical/smrt-core": "0.55.19",
62
- "@happyvertical/smrt-scanner": "0.55.19",
63
- "@happyvertical/smrt-svelte": "0.55.19",
64
- "@happyvertical/smrt-tenancy": "0.55.19",
65
- "@happyvertical/smrt-ui": "0.55.19",
66
- "@happyvertical/smrt-web": "0.55.19",
60
+ "@happyvertical/smrt-assets": "0.55.22",
61
+ "@happyvertical/smrt-core": "0.55.22",
62
+ "@happyvertical/smrt-scanner": "0.55.22",
63
+ "@happyvertical/smrt-svelte": "0.55.22",
64
+ "@happyvertical/smrt-tenancy": "0.55.22",
65
+ "@happyvertical/smrt-ui": "0.55.22",
66
+ "@happyvertical/smrt-web": "0.55.22",
67
67
  "@happyvertical/sql": "^0.103.5",
68
68
  "@happyvertical/utils": "^0.103.5",
69
69
  "cors": "^2.8.6",
@@ -84,7 +84,7 @@
84
84
  "@types/cors": "2.8.19",
85
85
  "@types/express": "^5.0.6",
86
86
  "@types/node": "24.13.6",
87
- "@happyvertical/smrt-vitest": "0.55.19",
87
+ "@happyvertical/smrt-vitest": "0.55.22",
88
88
  "concurrently": "^10.0.5",
89
89
  "svelte": "^5.57.1",
90
90
  "svelte-check": "^4.7.6",
@@ -1 +0,0 @@
1
- {"version":3,"file":"components-B_eBqqq7.js","names":[],"sources":["../../../src/lib/components/ProductCard.svelte","../../../src/lib/components/ProductForm.svelte"],"sourcesContent":["<script lang=\"ts\">\nimport { Button } from '@happyvertical/smrt-ui/ui';\nimport type { ProductData } from '../types';\n\ninterface Props {\n /** The product to display. */\n product: ProductData;\n /** Fired when the user clicks to edit the product. */\n onEdit?: (product: ProductData) => void;\n /** Fired when the user clicks to delete the product. */\n onDelete?: (id: string) => void;\n}\n\nconst { product, onEdit, onDelete }: Props = $props();\n</script>\n\n<div class=\"product-card\" data-smrt-component=\"ProductCard\">\n <div class=\"product-header\">\n <h3 class=\"product-name\">{product.name}</h3>\n {#if product.manufacturer}\n <div class=\"product-manufacturer\">{product.manufacturer}</div>\n {/if}\n </div>\n\n {#if product.model}\n <div class=\"product-model\">Model: {product.model}</div>\n {/if}\n\n {#if product.description}\n <p class=\"product-description\">{product.description}</p>\n {/if}\n\n <div class=\"product-meta\">\n {#if product.category}\n <div class=\"product-category\">Category: {product.category}</div>\n {/if}\n \n {#if product.tags && product.tags.length > 0}\n <div class=\"product-tags\">\n {#each product.tags as tag}\n <span class=\"tag\">{tag}</span>\n {/each}\n </div>\n {/if}\n </div>\n \n <div class=\"product-actions\">\n {#if onEdit}\n <Button type=\"button\" variant=\"secondary\" size=\"sm\" onclick={() => onEdit?.(product)}>\n Edit\n </Button>\n {/if}\n\n {#if onDelete}\n <Button type=\"button\" variant=\"danger\" size=\"sm\" onclick={() => onDelete?.(product.id)}>\n Delete\n </Button>\n {/if}\n </div>\n</div>\n\n<style>\n@layer smrt.reset, smrt.structure, smrt.theme;\n@layer smrt.theme {\n .product-card {\n border: 1px solid var(--smrt-color-outline-variant);\n border-radius: var(--smrt-radius-md);\n padding: 1rem;\n background: var(--smrt-color-surface);\n box-shadow: var(--smrt-elevation-1, 0 1px 3px color-mix(in srgb, var(--smrt-color-shadow) 10%, transparent));\n transition: box-shadow 0.2s;\n }\n\n .product-card:hover {\n box-shadow: var(--smrt-elevation-2, 0 4px 6px color-mix(in srgb, var(--smrt-color-shadow) 10%, transparent));\n }\n \n .product-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 0.5rem;\n }\n \n .product-name {\n margin: 0;\n font-size: var(--smrt-typography-title-medium-size, 1.125rem);\n font-weight: var(--smrt-typography-weight-semibold, 600);\n color: var(--smrt-color-on-surface);\n }\n\n .product-manufacturer {\n font-size: var(--smrt-typography-title-small-size, 0.875rem);\n font-weight: var(--smrt-typography-weight-medium, 500);\n color: var(--smrt-color-on-surface-variant);\n }\n\n .product-model {\n font-size: var(--smrt-typography-body-medium-size, 0.875rem);\n color: var(--smrt-color-on-surface-variant);\n margin-bottom: 0.5rem;\n }\n\n .product-category {\n font-size: var(--smrt-typography-label-medium-size, 0.75rem);\n font-weight: var(--smrt-typography-weight-medium, 500);\n color: var(--smrt-color-on-surface);\n background: var(--smrt-color-surface-container);\n padding: 0.25rem 0.5rem;\n border-radius: var(--smrt-radius-sm);\n display: inline-block;\n margin-bottom: 0.5rem;\n }\n \n .product-description {\n margin: 0.5rem 0;\n color: var(--smrt-color-on-surface-variant);\n font-size: var(--smrt-typography-body-medium-size, 0.875rem);\n line-height: var(--smrt-typography-body-medium-line-height, 1.4);\n }\n \n .product-meta {\n margin: 0.75rem 0;\n }\n \n \n .product-tags {\n margin-top: 0.5rem;\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n }\n \n .tag {\n background: var(--smrt-color-surface-container);\n color: var(--smrt-color-on-surface);\n padding: 0.125rem 0.5rem;\n border-radius: var(--smrt-radius-full);\n font-size: var(--smrt-typography-label-medium-size, 0.75rem);\n }\n\n .product-actions {\n display: flex;\n gap: 0.5rem;\n margin-top: 1rem;\n padding-top: 0.75rem;\n border-top: 1px solid var(--smrt-color-outline-variant);\n }\n}\n</style>","<script lang=\"ts\">\nimport { Form, Input, Textarea } from '@happyvertical/smrt-ui/forms';\nimport { useI18n } from '@happyvertical/smrt-ui/i18n';\nimport { Button } from '@happyvertical/smrt-ui/ui';\nimport { M } from '../i18n.js';\nimport type { ProductData } from '../types';\n\nconst { t } = useI18n();\n\ninterface Props {\n /** Product to populate the form with. */\n product?: Partial<ProductData>;\n /** Fired when the user submits the form. */\n onSubmit: (product: Partial<ProductData>) => void;\n /** Fired when the user clicks the cancel button. */\n onCancel?: () => void;\n /** Disables all inputs and shows \"Saving...\" when true. */\n loading?: boolean;\n}\n\nconst { product = {}, onSubmit, onCancel, loading = false }: Props = $props();\n\nconst formData = $state({\n name: product.name || '',\n description: product.description || '',\n price: product.price || 0,\n inStock: product.inStock ?? true,\n category: product.category || '',\n tags: product.tags?.join(', ') || '',\n});\n\nlet errors = $state<Record<string, string>>({});\n\nfunction validateForm() {\n errors = {};\n\n if (!formData.name.trim()) {\n errors.name = 'Product name is required';\n }\n\n if (formData.price < 0) {\n errors.price = 'Price must be non-negative';\n }\n\n return Object.keys(errors).length === 0;\n}\n\nfunction handleSubmit(event: Event) {\n event.preventDefault();\n\n if (!validateForm()) {\n return;\n }\n\n const productData: Partial<ProductData> = {\n ...product,\n name: formData.name.trim(),\n description: formData.description.trim() || undefined,\n price: formData.price,\n inStock: formData.inStock,\n category: formData.category.trim(),\n tags: formData.tags\n ? formData.tags\n .split(',')\n .map((tag) => tag.trim())\n .filter(Boolean)\n : [],\n };\n\n onSubmit(productData);\n}\n</script>\n\n<div class=\"product-form-shell\" data-smrt-component=\"ProductForm\">\n <Form onsubmit={handleSubmit} class=\"product-form\">\n <div class=\"form-group\">\n <label for=\"name\">{t(M['products.product_form.name_label'])}</label>\n <Input\n id=\"name\"\n type=\"text\"\n bind:value={formData.name}\n disabled={loading}\n class={errors.name ? 'error' : ''}\n placeholder={t(M['products.product_form.name_placeholder'])}\n />\n {#if errors.name}\n <span class=\"error-message\">{errors.name}</span>\n {/if}\n </div>\n\n <div class=\"form-group\">\n <label for=\"description\">Description</label>\n <Textarea\n id=\"description\"\n bind:value={formData.description}\n disabled={loading}\n placeholder={t(M['products.product_form.description_placeholder'])}\n rows={3}\n ></Textarea>\n </div>\n\n <div class=\"form-row\">\n <div class=\"form-group\">\n <label for=\"price\">Price *</label>\n <Input\n id=\"price\"\n type=\"number\"\n step=\"0.01\"\n min=\"0\"\n bind:value={formData.price}\n disabled={loading}\n class={errors.price ? 'error' : ''}\n placeholder=\"0.00\"\n />\n {#if errors.price}\n <span class=\"error-message\">{errors.price}</span>\n {/if}\n </div>\n\n <div class=\"form-group\">\n <label for=\"category\">Category</label>\n <Input\n id=\"category\"\n type=\"text\"\n bind:value={formData.category}\n disabled={loading}\n placeholder={t(M['products.product_form.category_placeholder'])}\n />\n </div>\n </div>\n\n <div class=\"form-group\">\n <label for=\"tags\">Tags</label>\n <Input\n id=\"tags\"\n type=\"text\"\n bind:value={formData.tags}\n disabled={loading}\n placeholder={t(M['products.product_form.tags_placeholder'])}\n />\n <small class=\"form-hint\">{t(M['products.product_form.tags_hint'])}</small>\n </div>\n\n <div class=\"form-group\">\n <label class=\"checkbox-label\">\n <!-- raw-primitive-allow: native checkbox; no Provider-free checkbox primitive (Toggle is a switch with different semantics, CheckboxInput requires a Provider) -->\n <input\n type=\"checkbox\"\n bind:checked={formData.inStock}\n disabled={loading}\n class=\"form-checkbox\"\n />\n {t(M['products.product_form.in_stock_label'])}\n </label>\n </div>\n\n <div class=\"form-actions\">\n {#if onCancel}\n <Button type=\"button\" variant=\"secondary\" onclick={onCancel} disabled={loading}>\n Cancel\n </Button>\n {/if}\n\n <Button type=\"submit\" variant=\"primary\" disabled={loading}>\n {#if loading}\n Saving...\n {:else}\n {product.id ? 'Update Product' : 'Create Product'}\n {/if}\n </Button>\n </div>\n </Form>\n</div>\n\n<style>\n@layer smrt.reset, smrt.structure, smrt.theme;\n@layer smrt.theme {\n .product-form-shell :global(.product-form) {\n max-width: 500px;\n padding: 1.5rem;\n background: var(--smrt-color-surface);\n border-radius: var(--smrt-radius-md);\n border: 1px solid var(--smrt-color-outline-variant);\n }\n\n .form-group {\n margin-bottom: 1rem;\n }\n\n .form-row {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1rem;\n }\n\n label {\n display: block;\n margin-bottom: 0.25rem;\n font-weight: var(--smrt-typography-weight-medium, 500);\n color: var(--smrt-color-on-surface);\n font-size: var(--smrt-typography-label-large-size, 0.875rem);\n }\n\n /* Error border on the migrated <Input>. The primitive renders the inner\n <input class=\"input error\"> inside its own component, so the scoped class\n can't reach it without :global (#1589). */\n .product-form-shell :global(.input.error) {\n border-color: var(--smrt-color-error);\n }\n\n .checkbox-label {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n cursor: pointer;\n }\n \n .form-checkbox {\n width: auto;\n }\n \n .form-hint {\n color: var(--smrt-color-on-surface-variant);\n font-size: var(--smrt-typography-body-small-size, 0.75rem);\n margin-top: 0.25rem;\n }\n\n .error-message {\n color: var(--smrt-color-error);\n font-size: var(--smrt-typography-label-medium-size, 0.75rem);\n margin-top: 0.25rem;\n display: block;\n }\n\n .form-actions {\n display: flex;\n gap: 0.75rem;\n justify-content: flex-end;\n margin-top: 1.5rem;\n padding-top: 1rem;\n border-top: 1px solid var(--smrt-color-outline-variant);\n }\n}\n</style>"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import "./__smrt-register__-CHWpaPZb.js";
2
- import "./Sku-CdhhTtjd.js";