@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.
- package/dist/lib/chunks/{__smrt-register__-CHWpaPZb.js → __smrt-register__-CdwszHtZ.js} +2 -2
- package/dist/lib/chunks/{__smrt-register__-CHWpaPZb.js.map → __smrt-register__-CdwszHtZ.js.map} +1 -1
- package/dist/lib/chunks/{collections-OOJeR05d.js → collections-CUwL7Dq6.js} +2 -2
- package/dist/lib/chunks/{collections-OOJeR05d.js.map → collections-CUwL7Dq6.js.map} +1 -1
- package/dist/lib/chunks/{components-B_eBqqq7.js → components-DMJz1geh.js} +2 -2
- package/dist/lib/chunks/components-DMJz1geh.js.map +1 -0
- package/dist/lib/chunks/{generated-DEBvTT0O.js → generated-Cwx8YMiS.js} +2 -2
- package/dist/lib/chunks/{generated-DEBvTT0O.js.map → generated-Cwx8YMiS.js.map} +1 -1
- package/dist/lib/chunks/models-CVqA-k81.js +2 -0
- package/dist/lib/collections.js +1 -1
- package/dist/lib/components.js +1 -1
- package/dist/lib/generated.js +1 -1
- package/dist/lib/index.js +5 -5
- package/dist/lib/lib/components/LiveProductList.svelte +2 -2
- package/dist/lib/lib/components/ProductCard.svelte +3 -3
- package/dist/lib/lib/components/ProductForm.svelte +3 -3
- package/dist/lib/lib/components/TestComponent.svelte +1 -1
- package/dist/lib/lib/components/auto-generated/AutoForm.svelte +3 -3
- package/dist/lib/lib/features/CategoryManager.svelte +1 -1
- package/dist/lib/lib/features/ProductCatalog.svelte +2 -2
- package/dist/lib/manifest.json +1 -1
- package/dist/lib/models.js +1 -1
- package/dist/lib/smrt-knowledge.json +3 -3
- package/dist/lib/smrt-products.css +5 -5
- package/package.json +9 -9
- package/dist/lib/chunks/components-B_eBqqq7.js.map +0 -1
- 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-
|
|
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__-
|
|
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-
|
|
7
|
+
//# sourceMappingURL=generated-Cwx8YMiS.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generated-
|
|
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"}
|
package/dist/lib/collections.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as CategoryCollection, n as ProductVariantCollection, r as MaterialCollection, t as SkuCollection } from "./chunks/collections-
|
|
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 };
|
package/dist/lib/components.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as ProductCard, t as ProductForm } from "./chunks/components-
|
|
1
|
+
import { n as ProductCard, t as ProductForm } from "./chunks/components-DMJz1geh.js";
|
|
2
2
|
export { ProductCard, ProductForm };
|
package/dist/lib/generated.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as autoGeneratedComponents } from "./chunks/generated-
|
|
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__-
|
|
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-
|
|
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-
|
|
8
|
-
import { t as autoGeneratedComponents } from "./chunks/generated-
|
|
9
|
-
import "./chunks/models-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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(.
|
|
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:
|
|
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:
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
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(
|
|
260
|
+
.error-state :global([data-smrt-component="Button"]) {
|
|
261
261
|
margin-top: 0.5rem;
|
|
262
262
|
}
|
|
263
263
|
|
package/dist/lib/manifest.json
CHANGED
package/dist/lib/models.js
CHANGED
|
@@ -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-
|
|
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.
|
|
6
|
+
"packageVersion": "0.55.22",
|
|
7
7
|
"sourceManifestPath": "dist/lib/manifest.json",
|
|
8
8
|
"agentDocPath": "AGENTS.md",
|
|
9
9
|
"sourceHashes": {
|
|
10
|
-
"manifest": "
|
|
11
|
-
"packageJson": "
|
|
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:
|
|
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:
|
|
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:
|
|
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 .
|
|
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:
|
|
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.
|
|
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.
|
|
61
|
-
"@happyvertical/smrt-core": "0.55.
|
|
62
|
-
"@happyvertical/smrt-scanner": "0.55.
|
|
63
|
-
"@happyvertical/smrt-svelte": "0.55.
|
|
64
|
-
"@happyvertical/smrt-tenancy": "0.55.
|
|
65
|
-
"@happyvertical/smrt-ui": "0.55.
|
|
66
|
-
"@happyvertical/smrt-web": "0.55.
|
|
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.
|
|
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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"}
|