@happyvertical/smrt-products 0.34.4 → 0.34.6

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.
@@ -1,14 +1,13 @@
1
1
  import "svelte/internal/disclose-version";
2
2
  import * as $ from "svelte/internal/client";
3
+ import { Button } from "@happyvertical/smrt-ui/ui";
3
4
  import { defineMessages, useI18n } from "@happyvertical/smrt-ui/i18n";
4
5
  var root_1$1 = $.from_html(`<div class="product-manufacturer svelte-11ja2cl"> </div>`);
5
6
  var root_2$1 = $.from_html(`<div class="product-model svelte-11ja2cl"> </div>`);
6
- var root_3$1 = $.from_html(`<p class="product-description svelte-11ja2cl"> </p>`);
7
+ var root_3 = $.from_html(`<p class="product-description svelte-11ja2cl"> </p>`);
7
8
  var root_4 = $.from_html(`<div class="product-category svelte-11ja2cl"> </div>`);
8
9
  var root_6 = $.from_html(`<span class="tag svelte-11ja2cl"> </span>`);
9
10
  var root_5 = $.from_html(`<div class="product-tags svelte-11ja2cl"></div>`);
10
- var root_7 = $.from_html(`<button type="button" class="edit-btn svelte-11ja2cl">Edit</button>`);
11
- var root_8 = $.from_html(`<button type="button" class="delete-btn svelte-11ja2cl">Delete</button>`);
12
11
  var root$1 = $.from_html(`<div class="product-card svelte-11ja2cl"><div class="product-header svelte-11ja2cl"><h3 class="product-name svelte-11ja2cl"> </h3> <!></div> <!> <!> <div class="product-meta svelte-11ja2cl"><!> <!></div> <div class="product-actions svelte-11ja2cl"><!> <!></div></div>`);
13
12
  function ProductCard($$anchor, $$props) {
14
13
  $.push($$props, true);
@@ -47,7 +46,7 @@ function ProductCard($$anchor, $$props) {
47
46
  var node_2 = $.sibling(node_1, 2);
48
47
  {
49
48
  var consequent_2 = ($$anchor2) => {
50
- var p = root_3$1();
49
+ var p = root_3();
51
50
  var text_3 = $.child(p, true);
52
51
  $.reset(p);
53
52
  $.template_effect(() => $.set_text(text_3, $$props.product.description));
@@ -94,9 +93,18 @@ function ProductCard($$anchor, $$props) {
94
93
  var node_5 = $.child(div_7);
95
94
  {
96
95
  var consequent_5 = ($$anchor2) => {
97
- var button = root_7();
98
- $.delegated("click", button, () => $$props.onEdit?.($$props.product));
99
- $.append($$anchor2, button);
96
+ Button($$anchor2, {
97
+ type: "button",
98
+ variant: "secondary",
99
+ size: "sm",
100
+ onclick: () => $$props.onEdit?.($$props.product),
101
+ children: ($$anchor3, $$slotProps) => {
102
+ $.next();
103
+ var text_6 = $.text("Edit");
104
+ $.append($$anchor3, text_6);
105
+ },
106
+ $$slots: { default: true }
107
+ });
100
108
  };
101
109
  $.if(node_5, ($$render) => {
102
110
  if ($$props.onEdit) $$render(consequent_5);
@@ -105,9 +113,18 @@ function ProductCard($$anchor, $$props) {
105
113
  var node_6 = $.sibling(node_5, 2);
106
114
  {
107
115
  var consequent_6 = ($$anchor2) => {
108
- var button_1 = root_8();
109
- $.delegated("click", button_1, () => $$props.onDelete?.($$props.product.id));
110
- $.append($$anchor2, button_1);
116
+ Button($$anchor2, {
117
+ type: "button",
118
+ variant: "danger",
119
+ size: "sm",
120
+ onclick: () => $$props.onDelete?.($$props.product.id),
121
+ children: ($$anchor3, $$slotProps) => {
122
+ $.next();
123
+ var text_7 = $.text("Delete");
124
+ $.append($$anchor3, text_7);
125
+ },
126
+ $$slots: { default: true }
127
+ });
111
128
  };
112
129
  $.if(node_6, ($$render) => {
113
130
  if ($$props.onDelete) $$render(consequent_6);
@@ -119,7 +136,6 @@ function ProductCard($$anchor, $$props) {
119
136
  $.append($$anchor, div);
120
137
  $.pop();
121
138
  }
122
- $.delegate(["click"]);
123
139
  const M = defineMessages({
124
140
  // App
125
141
  "products.app.categories_coming_soon": "Category management coming soon...",
@@ -210,8 +226,7 @@ const M = defineMessages({
210
226
  });
211
227
  var root_1 = $.from_html(`<span class="error-message svelte-1hh5ovx"> </span>`);
212
228
  var root_2 = $.from_html(`<span class="error-message svelte-1hh5ovx"> </span>`);
213
- var root_3 = $.from_html(`<button type="button" class="cancel-btn svelte-1hh5ovx">Cancel</button>`);
214
- var root = $.from_html(`<form class="product-form svelte-1hh5ovx"><div class="form-group svelte-1hh5ovx"><label for="name" class="svelte-1hh5ovx"> </label> <input id="name" type="text"/> <!></div> <div class="form-group svelte-1hh5ovx"><label for="description" class="svelte-1hh5ovx">Description</label> <textarea id="description" class="form-textarea svelte-1hh5ovx" rows="3"></textarea></div> <div class="form-row svelte-1hh5ovx"><div class="form-group svelte-1hh5ovx"><label for="price" class="svelte-1hh5ovx">Price *</label> <input id="price" type="number" step="0.01" min="0" placeholder="0.00"/> <!></div> <div class="form-group svelte-1hh5ovx"><label for="category" class="svelte-1hh5ovx">Category</label> <input id="category" type="text" class="form-input svelte-1hh5ovx"/></div></div> <div class="form-group svelte-1hh5ovx"><label for="tags" class="svelte-1hh5ovx">Tags</label> <input id="tags" type="text" class="form-input svelte-1hh5ovx"/> <small class="form-hint svelte-1hh5ovx"> </small></div> <div class="form-group svelte-1hh5ovx"><label class="checkbox-label svelte-1hh5ovx"><input type="checkbox" class="form-checkbox svelte-1hh5ovx"/> </label></div> <div class="form-actions svelte-1hh5ovx"><!> <button type="submit" class="submit-btn svelte-1hh5ovx"><!></button></div></form>`);
229
+ var root = $.from_html(`<form class="product-form svelte-1hh5ovx"><div class="form-group svelte-1hh5ovx"><label for="name" class="svelte-1hh5ovx"> </label> <input id="name" type="text"/> <!></div> <div class="form-group svelte-1hh5ovx"><label for="description" class="svelte-1hh5ovx">Description</label> <textarea id="description" class="form-textarea svelte-1hh5ovx" rows="3"></textarea></div> <div class="form-row svelte-1hh5ovx"><div class="form-group svelte-1hh5ovx"><label for="price" class="svelte-1hh5ovx">Price *</label> <input id="price" type="number" step="0.01" min="0" placeholder="0.00"/> <!></div> <div class="form-group svelte-1hh5ovx"><label for="category" class="svelte-1hh5ovx">Category</label> <input id="category" type="text" class="form-input svelte-1hh5ovx"/></div></div> <div class="form-group svelte-1hh5ovx"><label for="tags" class="svelte-1hh5ovx">Tags</label> <input id="tags" type="text" class="form-input svelte-1hh5ovx"/> <small class="form-hint svelte-1hh5ovx"> </small></div> <div class="form-group svelte-1hh5ovx"><label class="checkbox-label svelte-1hh5ovx"><input type="checkbox" class="form-checkbox svelte-1hh5ovx"/> </label></div> <div class="form-actions svelte-1hh5ovx"><!> <!></div></form>`);
215
230
  function ProductForm($$anchor, $$props) {
216
231
  $.push($$props, true);
217
232
  const { t } = useI18n();
@@ -319,35 +334,56 @@ function ProductForm($$anchor, $$props) {
319
334
  var node_2 = $.child(div_7);
320
335
  {
321
336
  var consequent_2 = ($$anchor2) => {
322
- var button = root_3();
323
- $.template_effect(() => button.disabled = loading());
324
- $.delegated("click", button, function(...$$args) {
325
- $$props.onCancel?.apply(this, $$args);
337
+ Button($$anchor2, {
338
+ type: "button",
339
+ variant: "secondary",
340
+ get onclick() {
341
+ return $$props.onCancel;
342
+ },
343
+ get disabled() {
344
+ return loading();
345
+ },
346
+ children: ($$anchor3, $$slotProps) => {
347
+ $.next();
348
+ var text_5 = $.text("Cancel");
349
+ $.append($$anchor3, text_5);
350
+ },
351
+ $$slots: { default: true }
326
352
  });
327
- $.append($$anchor2, button);
328
353
  };
329
354
  $.if(node_2, ($$render) => {
330
355
  if ($$props.onCancel) $$render(consequent_2);
331
356
  });
332
357
  }
333
- var button_1 = $.sibling(node_2, 2);
334
- var node_3 = $.child(button_1);
335
- {
336
- var consequent_3 = ($$anchor2) => {
337
- var text_5 = $.text("Saving...");
338
- $.append($$anchor2, text_5);
339
- };
340
- var alternate = ($$anchor2) => {
341
- var text_6 = $.text();
342
- $.template_effect(() => $.set_text(text_6, product().id ? "Update Product" : "Create Product"));
343
- $.append($$anchor2, text_6);
344
- };
345
- $.if(node_3, ($$render) => {
346
- if (loading()) $$render(consequent_3);
347
- else $$render(alternate, -1);
348
- });
349
- }
350
- $.reset(button_1);
358
+ var node_3 = $.sibling(node_2, 2);
359
+ Button(node_3, {
360
+ type: "submit",
361
+ variant: "primary",
362
+ get disabled() {
363
+ return loading();
364
+ },
365
+ children: ($$anchor2, $$slotProps) => {
366
+ var fragment_1 = $.comment();
367
+ var node_4 = $.first_child(fragment_1);
368
+ {
369
+ var consequent_3 = ($$anchor3) => {
370
+ var text_6 = $.text("Saving...");
371
+ $.append($$anchor3, text_6);
372
+ };
373
+ var alternate = ($$anchor3) => {
374
+ var text_7 = $.text();
375
+ $.template_effect(() => $.set_text(text_7, product().id ? "Update Product" : "Create Product"));
376
+ $.append($$anchor3, text_7);
377
+ };
378
+ $.if(node_4, ($$render) => {
379
+ if (loading()) $$render(consequent_3);
380
+ else $$render(alternate, -1);
381
+ });
382
+ }
383
+ $.append($$anchor2, fragment_1);
384
+ },
385
+ $$slots: { default: true }
386
+ });
351
387
  $.reset(div_7);
352
388
  $.reset(form);
353
389
  $.template_effect(
@@ -367,7 +403,6 @@ function ProductForm($$anchor, $$props) {
367
403
  $.set_text(text_3, $5);
368
404
  input_4.disabled = loading();
369
405
  $.set_text(text_4, ` ${$6 ?? ""}`);
370
- button_1.disabled = loading();
371
406
  },
372
407
  [
373
408
  () => t(M["products.product_form.name_label"]),
@@ -389,9 +424,8 @@ function ProductForm($$anchor, $$props) {
389
424
  $.append($$anchor, form);
390
425
  $.pop();
391
426
  }
392
- $.delegate(["click"]);
393
427
  export {
394
428
  ProductCard as P,
395
429
  ProductForm as a
396
430
  };
397
- //# sourceMappingURL=ProductForm-p4-xbubZ.js.map
431
+ //# sourceMappingURL=ProductForm-CukMCDEN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProductForm-CukMCDEN.js","sources":["../../../src/lib/components/ProductCard.svelte","../../../src/lib/i18n.ts","../../../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 product: ProductData;\n onEdit?: (product: ProductData) => void;\n onDelete?: (id: string) => void;\n}\n\nconst { product, onEdit, onDelete }: Props = $props();\n</script>\n\n<div class=\"product-card\">\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 .product-card {\n border: 1px solid var(--smrt-color-outline-variant, #e2e8f0);\n border-radius: var(--smrt-radius-md, 8px);\n padding: 1rem;\n background: var(--smrt-color-surface, #fff);\n box-shadow: var(--smrt-elevation-1, 0 1px 3px color-mix(in srgb, var(--smrt-color-shadow, #000) 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, #000) 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, #1f2937);\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, #6b7280);\n }\n\n .product-model {\n font-size: var(--smrt-typography-body-medium-size, 0.875rem);\n color: var(--smrt-color-on-surface-variant, #6b7280);\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, #374151);\n background: var(--smrt-color-surface-container, #f3f4f6);\n padding: 0.25rem 0.5rem;\n border-radius: var(--smrt-radius-sm, 4px);\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, #6b7280);\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, #f3f4f6);\n color: var(--smrt-color-on-surface, #374151);\n padding: 0.125rem 0.5rem;\n border-radius: var(--smrt-radius-full, 9999px);\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, #f3f4f6);\n }\n</style>","import { defineMessages } from '@happyvertical/smrt-ui/i18n';\n\nexport const M = defineMessages({\n // App\n 'products.app.categories_coming_soon': 'Category management coming soon...',\n 'products.app.analytics_coming_soon': 'Analytics dashboard coming soon...',\n\n // AppLayout\n 'products.app_layout.service_title': 'Product Service',\n 'products.app_layout.footer_copyright':\n '2024 SMRT Product Service - Auto-generated with ❤️',\n 'products.app_layout.api_docs': 'API Docs',\n 'products.app_layout.mcp_tools': 'MCP Tools',\n\n // DemoPage\n 'products.demo_page.title': 'SMRT Framework Demo',\n 'products.demo_page.subtitle':\n 'Define Once, Consume Everywhere - Progressive Customization',\n 'products.demo_page.custom_components_tab': 'Custom Components',\n 'products.demo_page.auto_generated_heading':\n 'Auto-Generated UI from SMRT Object',\n 'products.demo_page.auto_generated_description':\n 'This form is automatically generated from the Product class definition.\\n The field types, labels, and validation rules are inferred from the TypeScript schema.',\n 'products.demo_page.generated_form_heading': 'Generated Form',\n 'products.demo_page.auto_form_title': 'Auto-Generated Product Form',\n 'products.demo_page.generated_display_heading': 'Generated Display',\n 'products.demo_page.custom_components_heading':\n 'Custom Components with SMRT Integration',\n 'products.demo_page.custom_components_description':\n 'These are hand-crafted components that still leverage the SMRT data structure\\n but provide custom UI/UX for specific business requirements.',\n 'products.demo_page.custom_form_heading': 'Custom Form',\n 'products.demo_page.custom_display_heading': 'Custom Display',\n 'products.demo_page.progressive_heading': 'Progressive Customization',\n 'products.demo_page.progressive_description':\n 'Start with auto-generated components, then progressively customize as needed.\\n Both approaches use the same underlying SMRT Product model.',\n 'products.demo_page.feature_zero_config': '✅ Zero configuration',\n 'products.demo_page.feature_instant_ui': '✅ Instant UI from schema',\n 'products.demo_page.feature_type_safe': '✅ Type-safe by default',\n 'products.demo_page.feature_prototyping': '⚡ Perfect for prototyping',\n 'products.demo_page.custom_components_label': '🎨 Custom Components',\n 'products.demo_page.feature_tailored_ux': '✅ Tailored UX',\n 'products.demo_page.feature_business_workflows':\n '✅ Business-specific workflows',\n 'products.demo_page.feature_advanced_interactions':\n '✅ Advanced interactions',\n 'products.demo_page.simple_auto_form_title': 'Auto Form',\n 'products.demo_page.benefits_heading': 'SMRT Framework Benefits',\n 'products.demo_page.benefit_define_once_label': 'Define Once:',\n 'products.demo_page.benefit_define_once_text':\n 'Product class with @smrt decorator',\n 'products.demo_page.benefit_auto_generate_label': 'Auto-Generate:',\n 'products.demo_page.benefit_auto_generate_text':\n 'REST APIs, MCP tools, TypeScript clients, default UI',\n 'products.demo_page.benefit_progressive_label': 'Progressive Enhancement:',\n 'products.demo_page.benefit_progressive_text':\n 'Start with defaults, customize as needed',\n 'products.demo_page.benefit_type_safety_label': 'Type Safety:',\n 'products.demo_page.benefit_type_safety_text':\n 'End-to-end TypeScript integration',\n 'products.demo_page.benefit_multiple_consumption_label':\n 'Multiple Consumption:',\n 'products.demo_page.benefit_multiple_consumption_text':\n 'Library, federation, standalone',\n\n // ProductsPage\n 'products.products_page.description':\n 'Manage your product catalog with auto-generated CRUD operations, \\n real-time updates, and AI-powered tools via MCP.',\n 'products.products_page.auto_generated_text':\n 'REST API endpoints automatically created from @smrt() decorated Product class',\n 'products.products_page.ai_ready_heading': '🤖 AI Ready',\n 'products.products_page.ai_ready_text':\n 'MCP tools available for Claude and other AI models to interact with products',\n 'products.products_page.federatable_text':\n 'Components can be consumed by other applications via module federation',\n 'products.products_page.library_text':\n 'Install as NPM package: npm install @have/smrt-template',\n\n // ProductForm\n 'products.product_form.name_label': 'Product Name *',\n 'products.product_form.name_placeholder': 'Enter product name',\n 'products.product_form.description_placeholder':\n 'Product description (optional)',\n 'products.product_form.category_placeholder': 'Product category',\n 'products.product_form.tags_placeholder': 'tag1, tag2, tag3',\n 'products.product_form.tags_hint': 'Separate tags with commas',\n 'products.product_form.in_stock_label': 'In Stock',\n\n // TestComponent\n 'products.test_component.title': 'Test Component',\n\n // AutoForm\n 'products.auto_form.subtitle': 'Auto-generated from SMRT Product model',\n 'products.auto_form.debug_summary': 'Form Data (Debug)',\n\n // FieldRenderer\n 'products.field_renderer.array_hint': 'Enter values separated by commas',\n 'products.field_renderer.object_hint': 'Enter valid JSON',\n\n // CategoryManager\n 'products.category_manager.title': 'Category Manager',\n 'products.category_manager.subtitle': 'Manage product categories',\n 'products.category_manager.coming_soon':\n 'Category management feature coming soon...',\n 'products.category_manager.will_include': 'This will include:',\n 'products.category_manager.create_edit': 'Create and edit categories',\n 'products.category_manager.organize_hierarchy': 'Organize category hierarchy',\n 'products.category_manager.manage_permissions': 'Manage category permissions',\n 'products.category_manager.analytics': 'Category analytics',\n\n // ProductCatalog\n 'products.product_catalog.title': 'Product Catalog',\n 'products.product_catalog.in_stock': 'in stock',\n 'products.product_catalog.total_value': 'Total value:',\n 'products.product_catalog.search_placeholder': 'Search products...',\n 'products.product_catalog.all_categories': 'All Categories',\n 'products.product_catalog.add_product': 'Add Product',\n 'products.product_catalog.loading': 'Loading products...',\n 'products.product_catalog.empty':\n 'No products yet. Create your first product to get started!',\n 'products.product_catalog.create_first': 'Create First Product',\n 'products.product_catalog.no_match':\n 'No products match your search criteria.',\n});\n","<script lang=\"ts\">\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?: Partial<ProductData>;\n onSubmit: (product: Partial<ProductData>) => void;\n onCancel?: () => void;\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<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=\"form-input\"\n class:error={errors.name}\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 class=\"form-textarea\"\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=\"form-input\"\n class:error={errors.price}\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 class=\"form-input\"\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 class=\"form-input\"\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 <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\n<style>\n .product-form {\n max-width: 500px;\n padding: 1.5rem;\n background: var(--smrt-color-surface, #fff);\n border-radius: var(--smrt-radius-md, 8px);\n border: 1px solid var(--smrt-color-outline-variant, #e2e8f0);\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, #374151);\n font-size: var(--smrt-typography-label-large-size, 0.875rem);\n }\n\n .form-input, .form-textarea {\n width: 100%;\n padding: 0.5rem;\n border: 1px solid var(--smrt-color-outline-variant, #d1d5db);\n border-radius: var(--smrt-radius-sm, 4px);\n font-size: var(--smrt-typography-body-medium-size, 0.875rem);\n transition: border-color 0.2s;\n }\n\n .form-input:focus, .form-textarea:focus {\n outline: none;\n border-color: var(--smrt-color-primary, #3b82f6);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--smrt-color-primary, #3b82f6) 10%, transparent);\n }\n\n .form-input.error {\n border-color: var(--smrt-color-error, #dc2626);\n }\n \n .form-textarea {\n resize: vertical;\n min-height: 80px;\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, #6b7280);\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, #dc2626);\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, #f3f4f6);\n }\n</style>"],"names":["root","root_1","root_2","$$anchor"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { P, a } from "./chunks/ProductForm-p4-xbubZ.js";
1
+ import { P, a } from "./chunks/ProductForm-CukMCDEN.js";
2
2
  export {
3
3
  P as ProductCard,
4
4
  a as ProductForm
package/dist/lib/index.js CHANGED
@@ -6,7 +6,7 @@ import { default as default3 } from "@smrt/mcp";
6
6
  import { default as default4 } from "@smrt/routes";
7
7
  import { C, M, P, a, S } from "./chunks/SkuCollection-f_a3k93c.js";
8
8
  import { ProductAssetCollection } from "./chunks/ProductAssetCollection-B93HdSlX.js";
9
- import { P as P2, a as a2 } from "./chunks/ProductForm-p4-xbubZ.js";
9
+ import { P as P2, a as a2 } from "./chunks/ProductForm-CukMCDEN.js";
10
10
  import { a as a3 } from "./chunks/index-i3-ci1FB.js";
11
11
  import { P as Product, C as Category } from "./chunks/Sku-sl6xf1PR.js";
12
12
  import { M as M2, a as a4, b, c, S as S2 } from "./chunks/Sku-sl6xf1PR.js";
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ import { Button } from '@happyvertical/smrt-ui/ui';
2
3
  import type { ProductData } from '../types';
3
4
 
4
5
  interface Props {
@@ -42,15 +43,15 @@ const { product, onEdit, onDelete }: Props = $props();
42
43
 
43
44
  <div class="product-actions">
44
45
  {#if onEdit}
45
- <button type="button" onclick={() => onEdit?.(product)} class="edit-btn">
46
+ <Button type="button" variant="secondary" size="sm" onclick={() => onEdit?.(product)}>
46
47
  Edit
47
- </button>
48
+ </Button>
48
49
  {/if}
49
-
50
+
50
51
  {#if onDelete}
51
- <button type="button" onclick={() => onDelete?.(product.id)} class="delete-btn">
52
+ <Button type="button" variant="danger" size="sm" onclick={() => onDelete?.(product.id)}>
52
53
  Delete
53
- </button>
54
+ </Button>
54
55
  {/if}
55
56
  </div>
56
57
  </div>
@@ -140,34 +141,4 @@ const { product, onEdit, onDelete }: Props = $props();
140
141
  padding-top: 0.75rem;
141
142
  border-top: 1px solid var(--smrt-color-outline-variant, #f3f4f6);
142
143
  }
143
-
144
- .edit-btn, .delete-btn {
145
- padding: 0.375rem 0.75rem;
146
- border-radius: var(--smrt-radius-sm, 4px);
147
- font-size: var(--smrt-typography-label-large-size, 0.875rem);
148
- font-weight: var(--smrt-typography-weight-medium, 500);
149
- border: 1px solid;
150
- cursor: pointer;
151
- transition: all 0.2s;
152
- }
153
-
154
- .edit-btn {
155
- background: var(--smrt-color-surface-container-low, #f9fafb);
156
- border-color: var(--smrt-color-outline-variant, #d1d5db);
157
- color: var(--smrt-color-on-surface, #374151);
158
- }
159
-
160
- .edit-btn:hover {
161
- background: var(--smrt-color-surface-container, #f3f4f6);
162
- }
163
-
164
- .delete-btn {
165
- background: var(--smrt-color-error-container, #fef2f2);
166
- border-color: var(--smrt-color-error, #fecaca);
167
- color: var(--smrt-color-error, #dc2626);
168
- }
169
-
170
- .delete-btn:hover {
171
- background: var(--smrt-color-error-container, #fee2e2);
172
- }
173
144
  </style>
@@ -1 +1 @@
1
- {"version":3,"file":"ProductCard.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/ProductCard.svelte"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAG5C,UAAU,KAAK;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAwDD,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"ProductCard.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/ProductCard.svelte"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAG5C,UAAU,KAAK;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAyDD,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
3
+ import { Button } from '@happyvertical/smrt-ui/ui';
3
4
  import { M } from '../i18n.js';
4
5
  import type { ProductData } from '../types';
5
6
 
@@ -153,18 +154,18 @@ function handleSubmit(event: Event) {
153
154
 
154
155
  <div class="form-actions">
155
156
  {#if onCancel}
156
- <button type="button" onclick={onCancel} disabled={loading} class="cancel-btn">
157
+ <Button type="button" variant="secondary" onclick={onCancel} disabled={loading}>
157
158
  Cancel
158
- </button>
159
+ </Button>
159
160
  {/if}
160
-
161
- <button type="submit" disabled={loading} class="submit-btn">
161
+
162
+ <Button type="submit" variant="primary" disabled={loading}>
162
163
  {#if loading}
163
164
  Saving...
164
165
  {:else}
165
166
  {product.id ? 'Update Product' : 'Create Product'}
166
167
  {/if}
167
- </button>
168
+ </Button>
168
169
  </div>
169
170
  </form>
170
171
 
@@ -251,39 +252,4 @@ function handleSubmit(event: Event) {
251
252
  padding-top: 1rem;
252
253
  border-top: 1px solid var(--smrt-color-outline-variant, #f3f4f6);
253
254
  }
254
-
255
- .cancel-btn, .submit-btn {
256
- padding: 0.5rem 1rem;
257
- border-radius: var(--smrt-radius-sm, 4px);
258
- font-size: var(--smrt-typography-label-large-size, 0.875rem);
259
- font-weight: var(--smrt-typography-weight-medium, 500);
260
- cursor: pointer;
261
- border: 1px solid;
262
- transition: all 0.2s;
263
- }
264
-
265
- .cancel-btn {
266
- background: var(--smrt-color-surface, #fff);
267
- border-color: var(--smrt-color-outline-variant, #d1d5db);
268
- color: var(--smrt-color-on-surface, #374151);
269
- }
270
-
271
- .cancel-btn:hover:not(:disabled) {
272
- background: var(--smrt-color-surface-container-low, #f9fafb);
273
- }
274
-
275
- .submit-btn {
276
- background: var(--smrt-color-primary, #3b82f6);
277
- border-color: var(--smrt-color-primary, #3b82f6);
278
- color: var(--smrt-color-on-primary, white);
279
- }
280
-
281
- .submit-btn:hover:not(:disabled) {
282
- background: var(--smrt-color-primary, #2563eb);
283
- }
284
-
285
- .submit-btn:disabled, .cancel-btn:disabled {
286
- opacity: 0.5;
287
- cursor: not-allowed;
288
- }
289
255
  </style>
@@ -1 +1 @@
1
- {"version":3,"file":"ProductForm.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/ProductForm.svelte"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAG5C,UAAU,KAAK;IACb,OAAO,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/B,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IAClD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA0HD,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"ProductForm.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/ProductForm.svelte"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAG5C,UAAU,KAAK;IACb,OAAO,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/B,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IAClD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA2HD,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
8
+ import { Button } from '@happyvertical/smrt-ui/ui';
8
9
  import { M } from '../../i18n.js';
9
10
  import type { ProductData } from '../../types';
10
11
  import FieldRenderer from './FieldRenderer.svelte';
@@ -128,12 +129,12 @@ function _getFieldType(
128
129
 
129
130
  {#if !readonly}
130
131
  <div class="form-actions">
131
- <button type="submit" class="submit-btn">
132
+ <Button type="submit" variant="primary">
132
133
  {submitLabel}
133
- </button>
134
- <button type="button" class="reset-btn" onclick={() => formData = {}}>
134
+ </Button>
135
+ <Button type="button" variant="secondary" onclick={() => formData = {}}>
135
136
  Reset
136
- </button>
137
+ </Button>
137
138
  </div>
138
139
  {/if}
139
140
  </form>
@@ -187,36 +188,6 @@ function _getFieldType(
187
188
  border-top: 1px solid var(--smrt-color-outline-variant, #e5e7eb);
188
189
  }
189
190
 
190
- .submit-btn {
191
- background: var(--smrt-color-primary, #3b82f6);
192
- color: var(--smrt-color-on-primary, white);
193
- border: none;
194
- padding: 0.75rem 1.5rem;
195
- border-radius: var(--smrt-radius-sm, 0.375rem);
196
- font-weight: var(--smrt-typography-weight-medium, 500);
197
- cursor: pointer;
198
- transition: background-color 0.2s;
199
- }
200
-
201
- .submit-btn:hover {
202
- background: var(--smrt-color-primary, #2563eb);
203
- }
204
-
205
- .reset-btn {
206
- background: var(--smrt-color-surface-container, #f3f4f6);
207
- color: var(--smrt-color-on-surface, #374151);
208
- border: 1px solid var(--smrt-color-outline-variant, #d1d5db);
209
- padding: 0.75rem 1.5rem;
210
- border-radius: var(--smrt-radius-sm, 0.375rem);
211
- font-weight: var(--smrt-typography-weight-medium, 500);
212
- cursor: pointer;
213
- transition: background-color 0.2s;
214
- }
215
-
216
- .reset-btn:hover {
217
- background: var(--smrt-color-surface-container-high, #e5e7eb);
218
- }
219
-
220
191
  .form-debug {
221
192
  margin-top: 2rem;
222
193
  padding: 1rem;
@@ -1 +1 @@
1
- {"version":3,"file":"AutoForm.svelte.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/auto-generated/AutoForm.svelte.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C,UAAU,KAAK;IACb,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;CACxC;AAmID,QAAA,MAAM,QAAQ,2CAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"AutoForm.svelte.d.ts","sourceRoot":"","sources":["../../../../../src/lib/components/auto-generated/AutoForm.svelte.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C,UAAU,KAAK;IACb,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;CACxC;AAoID,QAAA,MAAM,QAAQ,2CAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
3
+ import { Button } from '@happyvertical/smrt-ui/ui';
3
4
  import { onMount } from 'svelte';
4
5
  import ProductCard from '../components/ProductCard.svelte';
5
6
  import ProductForm from '../components/ProductForm.svelte';
@@ -119,13 +120,13 @@ function handleCancelForm() {
119
120
  </div>
120
121
 
121
122
  {#if !readonly && (showCreateForm || productStore.items.length === 0)}
122
- <button
123
- type="button"
123
+ <Button
124
+ type="button"
125
+ variant="primary"
124
126
  onclick={handleCreateProduct}
125
- class="create-btn"
126
127
  >
127
128
  {t(M['products.product_catalog.add_product'])}
128
- </button>
129
+ </Button>
129
130
  {/if}
130
131
  </div>
131
132
 
@@ -136,18 +137,18 @@ function handleCancelForm() {
136
137
  {:else if productStore.error}
137
138
  <div class="error-state" role="alert" aria-live="assertive">
138
139
  <p>Error: {productStore.error}</p>
139
- <button type="button" onclick={() => productStore.loadProducts()}>
140
+ <Button type="button" variant="danger" onclick={() => productStore.loadProducts()}>
140
141
  Retry
141
- </button>
142
+ </Button>
142
143
  </div>
143
144
  {:else if filteredProducts.length === 0}
144
145
  <div class="empty-state" role="status" aria-live="polite">
145
146
  {#if productStore.items.length === 0}
146
147
  <p>{t(M['products.product_catalog.empty'])}</p>
147
148
  {#if !readonly}
148
- <button type="button" onclick={handleCreateProduct} class="create-btn">
149
+ <Button type="button" variant="primary" onclick={handleCreateProduct}>
149
150
  {t(M['products.product_catalog.create_first'])}
150
- </button>
151
+ </Button>
151
152
  {/if}
152
153
  {:else}
153
154
  <p>{t(M['products.product_catalog.no_match'])}</p>
@@ -240,21 +241,6 @@ function handleCancelForm() {
240
241
  min-width: 150px;
241
242
  }
242
243
 
243
- .create-btn {
244
- background: var(--smrt-color-primary, #3b82f6);
245
- color: var(--smrt-color-on-primary, white);
246
- border: none;
247
- padding: 0.5rem 1rem;
248
- border-radius: var(--smrt-radius-sm, 4px);
249
- font-weight: var(--smrt-typography-weight-medium, 500);
250
- cursor: pointer;
251
- transition: background-color 0.2s;
252
- }
253
-
254
- .create-btn:hover {
255
- background: var(--smrt-color-primary, #2563eb);
256
- }
257
-
258
244
  .products-grid {
259
245
  display: grid;
260
246
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
@@ -267,14 +253,12 @@ function handleCancelForm() {
267
253
  color: var(--smrt-color-on-surface-variant, #6b7280);
268
254
  }
269
255
 
270
- .error-state button {
256
+ /* Restore the retry button's spacing from the error message. The old
257
+ `.error-state button` rule can't reach the <button> rendered inside the
258
+ smrt-ui <Button>, so pierce into it with `:global` (#1589); the danger
259
+ variant already supplies the background/color the old rule set. */
260
+ .error-state :global(.button) {
271
261
  margin-top: 0.5rem;
272
- background: var(--smrt-color-error, #dc2626);
273
- color: var(--smrt-color-on-error, white);
274
- border: none;
275
- padding: 0.5rem 1rem;
276
- border-radius: var(--smrt-radius-sm, 4px);
277
- cursor: pointer;
278
262
  }
279
263
 
280
264
  .form-overlay {
@@ -1 +1 @@
1
- {"version":3,"file":"ProductCatalog.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/features/ProductCatalog.svelte"],"names":[],"mappings":"AAYA,UAAU,KAAK;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAmKD,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"ProductCatalog.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/features/ProductCatalog.svelte"],"names":[],"mappings":"AAaA,UAAU,KAAK;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAoKD,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "version": "1.0.0",
3
- "timestamp": 1782257849837,
3
+ "timestamp": 1782278452967,
4
4
  "packageName": "@happyvertical/smrt-products",
5
- "packageVersion": "0.34.4",
5
+ "packageVersion": "0.34.6",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-products:CategoryCollection": {
8
8
  "name": "categorycollection",
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "generatedAt": "2026-06-23T23:37:31.073Z",
3
+ "generatedAt": "2026-06-24T05:20:53.581Z",
4
4
  "packageName": "@happyvertical/smrt-products",
5
- "packageVersion": "0.34.4",
5
+ "packageVersion": "0.34.6",
6
6
  "sourceManifestPath": "dist/lib/manifest.json",
7
7
  "agentDocPath": "AGENTS.md",
8
8
  "sourceHashes": {
9
- "manifest": "45b07077d5e341f13c0982fbf87d5eb85c39e44c9db847c28e31adbe4c27a5ca",
10
- "packageJson": "b796b7800f4c8ff3ac5ef6c43a3eb2933703f3bb342de6fe33928e22b2f444c9",
9
+ "manifest": "584ad2da857b7180b8a585c41e0975b7743a07f6ad3ffc172186e396cd814cb7",
10
+ "packageJson": "5a90519cc03f1b0745852b4c8b691d0a03199722ab64cdf53425665e20be1ec5",
11
11
  "agents": "4ca8837df73cf8b966b65cea639a058baa8f92ae536f3cd5036546fcbfeb37c8"
12
12
  },
13
13
  "exports": [
@@ -83,36 +83,6 @@
83
83
  padding-top: 0.75rem;
84
84
  border-top: 1px solid var(--smrt-color-outline-variant, #f3f4f6);
85
85
  }
86
-
87
- .edit-btn.svelte-11ja2cl, .delete-btn.svelte-11ja2cl {
88
- padding: 0.375rem 0.75rem;
89
- border-radius: var(--smrt-radius-sm, 4px);
90
- font-size: var(--smrt-typography-label-large-size, 0.875rem);
91
- font-weight: var(--smrt-typography-weight-medium, 500);
92
- border: 1px solid;
93
- cursor: pointer;
94
- transition: all 0.2s;
95
- }
96
-
97
- .edit-btn.svelte-11ja2cl {
98
- background: var(--smrt-color-surface-container-low, #f9fafb);
99
- border-color: var(--smrt-color-outline-variant, #d1d5db);
100
- color: var(--smrt-color-on-surface, #374151);
101
- }
102
-
103
- .edit-btn.svelte-11ja2cl:hover {
104
- background: var(--smrt-color-surface-container, #f3f4f6);
105
- }
106
-
107
- .delete-btn.svelte-11ja2cl {
108
- background: var(--smrt-color-error-container, #fef2f2);
109
- border-color: var(--smrt-color-error, #fecaca);
110
- color: var(--smrt-color-error, #dc2626);
111
- }
112
-
113
- .delete-btn.svelte-11ja2cl:hover {
114
- background: var(--smrt-color-error-container, #fee2e2);
115
- }
116
86
 
117
87
  .product-form.svelte-1hh5ovx {
118
88
  max-width: 500px;
@@ -196,38 +166,3 @@
196
166
  padding-top: 1rem;
197
167
  border-top: 1px solid var(--smrt-color-outline-variant, #f3f4f6);
198
168
  }
199
-
200
- .cancel-btn.svelte-1hh5ovx, .submit-btn.svelte-1hh5ovx {
201
- padding: 0.5rem 1rem;
202
- border-radius: var(--smrt-radius-sm, 4px);
203
- font-size: var(--smrt-typography-label-large-size, 0.875rem);
204
- font-weight: var(--smrt-typography-weight-medium, 500);
205
- cursor: pointer;
206
- border: 1px solid;
207
- transition: all 0.2s;
208
- }
209
-
210
- .cancel-btn.svelte-1hh5ovx {
211
- background: var(--smrt-color-surface, #fff);
212
- border-color: var(--smrt-color-outline-variant, #d1d5db);
213
- color: var(--smrt-color-on-surface, #374151);
214
- }
215
-
216
- .cancel-btn.svelte-1hh5ovx:hover:not(:disabled) {
217
- background: var(--smrt-color-surface-container-low, #f9fafb);
218
- }
219
-
220
- .submit-btn.svelte-1hh5ovx {
221
- background: var(--smrt-color-primary, #3b82f6);
222
- border-color: var(--smrt-color-primary, #3b82f6);
223
- color: var(--smrt-color-on-primary, white);
224
- }
225
-
226
- .submit-btn.svelte-1hh5ovx:hover:not(:disabled) {
227
- background: var(--smrt-color-primary, #2563eb);
228
- }
229
-
230
- .submit-btn.svelte-1hh5ovx:disabled, .cancel-btn.svelte-1hh5ovx:disabled {
231
- opacity: 0.5;
232
- cursor: not-allowed;
233
- }
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-products",
3
- "version": "0.34.4",
3
+ "version": "0.34.6",
4
4
  "description": "SMRT products module: triple-purpose microservice template for standalone apps, federated modules, and NPM libraries",
5
5
  "author": "HappyVertical",
6
6
  "type": "module",
7
+ "smrtRawPrimitives": "strict-buttons",
7
8
  "main": "dist/lib/index.js",
8
9
  "types": "dist/lib/index.d.ts",
9
10
  "files": [
@@ -54,11 +55,11 @@
54
55
  "@happyvertical/utils": "^0.74.7",
55
56
  "cors": "^2.8.5",
56
57
  "express": "^5.2.1",
57
- "@happyvertical/smrt-core": "0.34.4",
58
- "@happyvertical/smrt-scanner": "0.34.4",
59
- "@happyvertical/smrt-tenancy": "0.34.4",
60
- "@happyvertical/smrt-ui": "0.34.4",
61
- "@happyvertical/smrt-assets": "0.34.4"
58
+ "@happyvertical/smrt-assets": "0.34.6",
59
+ "@happyvertical/smrt-core": "0.34.6",
60
+ "@happyvertical/smrt-scanner": "0.34.6",
61
+ "@happyvertical/smrt-tenancy": "0.34.6",
62
+ "@happyvertical/smrt-ui": "0.34.6"
62
63
  },
63
64
  "peerDependencies": {
64
65
  "svelte": "^5.46.4"
@@ -81,7 +82,7 @@
81
82
  "typescript": "^5.9.3",
82
83
  "vite": "^7.3.1",
83
84
  "vitest": "^4.0.17",
84
- "@happyvertical/smrt-vitest": "0.34.4"
85
+ "@happyvertical/smrt-vitest": "0.34.6"
85
86
  },
86
87
  "keywords": [
87
88
  "smrt",
@@ -1 +0,0 @@
1
- {"version":3,"file":"ProductForm-p4-xbubZ.js","sources":["../../../src/lib/components/ProductCard.svelte","../../../src/lib/i18n.ts","../../../src/lib/components/ProductForm.svelte"],"sourcesContent":["<script lang=\"ts\">\nimport type { ProductData } from '../types';\n\ninterface Props {\n product: ProductData;\n onEdit?: (product: ProductData) => void;\n onDelete?: (id: string) => void;\n}\n\nconst { product, onEdit, onDelete }: Props = $props();\n</script>\n\n<div class=\"product-card\">\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\" onclick={() => onEdit?.(product)} class=\"edit-btn\">\n Edit\n </button>\n {/if}\n \n {#if onDelete}\n <button type=\"button\" onclick={() => onDelete?.(product.id)} class=\"delete-btn\">\n Delete\n </button>\n {/if}\n </div>\n</div>\n\n<style>\n .product-card {\n border: 1px solid var(--smrt-color-outline-variant, #e2e8f0);\n border-radius: var(--smrt-radius-md, 8px);\n padding: 1rem;\n background: var(--smrt-color-surface, #fff);\n box-shadow: var(--smrt-elevation-1, 0 1px 3px color-mix(in srgb, var(--smrt-color-shadow, #000) 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, #000) 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, #1f2937);\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, #6b7280);\n }\n\n .product-model {\n font-size: var(--smrt-typography-body-medium-size, 0.875rem);\n color: var(--smrt-color-on-surface-variant, #6b7280);\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, #374151);\n background: var(--smrt-color-surface-container, #f3f4f6);\n padding: 0.25rem 0.5rem;\n border-radius: var(--smrt-radius-sm, 4px);\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, #6b7280);\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, #f3f4f6);\n color: var(--smrt-color-on-surface, #374151);\n padding: 0.125rem 0.5rem;\n border-radius: var(--smrt-radius-full, 9999px);\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, #f3f4f6);\n }\n \n .edit-btn, .delete-btn {\n padding: 0.375rem 0.75rem;\n border-radius: var(--smrt-radius-sm, 4px);\n font-size: var(--smrt-typography-label-large-size, 0.875rem);\n font-weight: var(--smrt-typography-weight-medium, 500);\n border: 1px solid;\n cursor: pointer;\n transition: all 0.2s;\n }\n \n .edit-btn {\n background: var(--smrt-color-surface-container-low, #f9fafb);\n border-color: var(--smrt-color-outline-variant, #d1d5db);\n color: var(--smrt-color-on-surface, #374151);\n }\n\n .edit-btn:hover {\n background: var(--smrt-color-surface-container, #f3f4f6);\n }\n\n .delete-btn {\n background: var(--smrt-color-error-container, #fef2f2);\n border-color: var(--smrt-color-error, #fecaca);\n color: var(--smrt-color-error, #dc2626);\n }\n\n .delete-btn:hover {\n background: var(--smrt-color-error-container, #fee2e2);\n }\n</style>","import { defineMessages } from '@happyvertical/smrt-ui/i18n';\n\nexport const M = defineMessages({\n // App\n 'products.app.categories_coming_soon': 'Category management coming soon...',\n 'products.app.analytics_coming_soon': 'Analytics dashboard coming soon...',\n\n // AppLayout\n 'products.app_layout.service_title': 'Product Service',\n 'products.app_layout.footer_copyright':\n '2024 SMRT Product Service - Auto-generated with ❤️',\n 'products.app_layout.api_docs': 'API Docs',\n 'products.app_layout.mcp_tools': 'MCP Tools',\n\n // DemoPage\n 'products.demo_page.title': 'SMRT Framework Demo',\n 'products.demo_page.subtitle':\n 'Define Once, Consume Everywhere - Progressive Customization',\n 'products.demo_page.custom_components_tab': 'Custom Components',\n 'products.demo_page.auto_generated_heading':\n 'Auto-Generated UI from SMRT Object',\n 'products.demo_page.auto_generated_description':\n 'This form is automatically generated from the Product class definition.\\n The field types, labels, and validation rules are inferred from the TypeScript schema.',\n 'products.demo_page.generated_form_heading': 'Generated Form',\n 'products.demo_page.auto_form_title': 'Auto-Generated Product Form',\n 'products.demo_page.generated_display_heading': 'Generated Display',\n 'products.demo_page.custom_components_heading':\n 'Custom Components with SMRT Integration',\n 'products.demo_page.custom_components_description':\n 'These are hand-crafted components that still leverage the SMRT data structure\\n but provide custom UI/UX for specific business requirements.',\n 'products.demo_page.custom_form_heading': 'Custom Form',\n 'products.demo_page.custom_display_heading': 'Custom Display',\n 'products.demo_page.progressive_heading': 'Progressive Customization',\n 'products.demo_page.progressive_description':\n 'Start with auto-generated components, then progressively customize as needed.\\n Both approaches use the same underlying SMRT Product model.',\n 'products.demo_page.feature_zero_config': '✅ Zero configuration',\n 'products.demo_page.feature_instant_ui': '✅ Instant UI from schema',\n 'products.demo_page.feature_type_safe': '✅ Type-safe by default',\n 'products.demo_page.feature_prototyping': '⚡ Perfect for prototyping',\n 'products.demo_page.custom_components_label': '🎨 Custom Components',\n 'products.demo_page.feature_tailored_ux': '✅ Tailored UX',\n 'products.demo_page.feature_business_workflows':\n '✅ Business-specific workflows',\n 'products.demo_page.feature_advanced_interactions':\n '✅ Advanced interactions',\n 'products.demo_page.simple_auto_form_title': 'Auto Form',\n 'products.demo_page.benefits_heading': 'SMRT Framework Benefits',\n 'products.demo_page.benefit_define_once_label': 'Define Once:',\n 'products.demo_page.benefit_define_once_text':\n 'Product class with @smrt decorator',\n 'products.demo_page.benefit_auto_generate_label': 'Auto-Generate:',\n 'products.demo_page.benefit_auto_generate_text':\n 'REST APIs, MCP tools, TypeScript clients, default UI',\n 'products.demo_page.benefit_progressive_label': 'Progressive Enhancement:',\n 'products.demo_page.benefit_progressive_text':\n 'Start with defaults, customize as needed',\n 'products.demo_page.benefit_type_safety_label': 'Type Safety:',\n 'products.demo_page.benefit_type_safety_text':\n 'End-to-end TypeScript integration',\n 'products.demo_page.benefit_multiple_consumption_label':\n 'Multiple Consumption:',\n 'products.demo_page.benefit_multiple_consumption_text':\n 'Library, federation, standalone',\n\n // ProductsPage\n 'products.products_page.description':\n 'Manage your product catalog with auto-generated CRUD operations, \\n real-time updates, and AI-powered tools via MCP.',\n 'products.products_page.auto_generated_text':\n 'REST API endpoints automatically created from @smrt() decorated Product class',\n 'products.products_page.ai_ready_heading': '🤖 AI Ready',\n 'products.products_page.ai_ready_text':\n 'MCP tools available for Claude and other AI models to interact with products',\n 'products.products_page.federatable_text':\n 'Components can be consumed by other applications via module federation',\n 'products.products_page.library_text':\n 'Install as NPM package: npm install @have/smrt-template',\n\n // ProductForm\n 'products.product_form.name_label': 'Product Name *',\n 'products.product_form.name_placeholder': 'Enter product name',\n 'products.product_form.description_placeholder':\n 'Product description (optional)',\n 'products.product_form.category_placeholder': 'Product category',\n 'products.product_form.tags_placeholder': 'tag1, tag2, tag3',\n 'products.product_form.tags_hint': 'Separate tags with commas',\n 'products.product_form.in_stock_label': 'In Stock',\n\n // TestComponent\n 'products.test_component.title': 'Test Component',\n\n // AutoForm\n 'products.auto_form.subtitle': 'Auto-generated from SMRT Product model',\n 'products.auto_form.debug_summary': 'Form Data (Debug)',\n\n // FieldRenderer\n 'products.field_renderer.array_hint': 'Enter values separated by commas',\n 'products.field_renderer.object_hint': 'Enter valid JSON',\n\n // CategoryManager\n 'products.category_manager.title': 'Category Manager',\n 'products.category_manager.subtitle': 'Manage product categories',\n 'products.category_manager.coming_soon':\n 'Category management feature coming soon...',\n 'products.category_manager.will_include': 'This will include:',\n 'products.category_manager.create_edit': 'Create and edit categories',\n 'products.category_manager.organize_hierarchy': 'Organize category hierarchy',\n 'products.category_manager.manage_permissions': 'Manage category permissions',\n 'products.category_manager.analytics': 'Category analytics',\n\n // ProductCatalog\n 'products.product_catalog.title': 'Product Catalog',\n 'products.product_catalog.in_stock': 'in stock',\n 'products.product_catalog.total_value': 'Total value:',\n 'products.product_catalog.search_placeholder': 'Search products...',\n 'products.product_catalog.all_categories': 'All Categories',\n 'products.product_catalog.add_product': 'Add Product',\n 'products.product_catalog.loading': 'Loading products...',\n 'products.product_catalog.empty':\n 'No products yet. Create your first product to get started!',\n 'products.product_catalog.create_first': 'Create First Product',\n 'products.product_catalog.no_match':\n 'No products match your search criteria.',\n});\n","<script lang=\"ts\">\nimport { useI18n } from '@happyvertical/smrt-ui/i18n';\nimport { M } from '../i18n.js';\nimport type { ProductData } from '../types';\n\nconst { t } = useI18n();\n\ninterface Props {\n product?: Partial<ProductData>;\n onSubmit: (product: Partial<ProductData>) => void;\n onCancel?: () => void;\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<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=\"form-input\"\n class:error={errors.name}\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 class=\"form-textarea\"\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=\"form-input\"\n class:error={errors.price}\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 class=\"form-input\"\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 class=\"form-input\"\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 <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\" onclick={onCancel} disabled={loading} class=\"cancel-btn\">\n Cancel\n </button>\n {/if}\n \n <button type=\"submit\" disabled={loading} class=\"submit-btn\">\n {#if loading}\n Saving...\n {:else}\n {product.id ? 'Update Product' : 'Create Product'}\n {/if}\n </button>\n </div>\n</form>\n\n<style>\n .product-form {\n max-width: 500px;\n padding: 1.5rem;\n background: var(--smrt-color-surface, #fff);\n border-radius: var(--smrt-radius-md, 8px);\n border: 1px solid var(--smrt-color-outline-variant, #e2e8f0);\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, #374151);\n font-size: var(--smrt-typography-label-large-size, 0.875rem);\n }\n\n .form-input, .form-textarea {\n width: 100%;\n padding: 0.5rem;\n border: 1px solid var(--smrt-color-outline-variant, #d1d5db);\n border-radius: var(--smrt-radius-sm, 4px);\n font-size: var(--smrt-typography-body-medium-size, 0.875rem);\n transition: border-color 0.2s;\n }\n\n .form-input:focus, .form-textarea:focus {\n outline: none;\n border-color: var(--smrt-color-primary, #3b82f6);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--smrt-color-primary, #3b82f6) 10%, transparent);\n }\n\n .form-input.error {\n border-color: var(--smrt-color-error, #dc2626);\n }\n \n .form-textarea {\n resize: vertical;\n min-height: 80px;\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, #6b7280);\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, #dc2626);\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, #f3f4f6);\n }\n \n .cancel-btn, .submit-btn {\n padding: 0.5rem 1rem;\n border-radius: var(--smrt-radius-sm, 4px);\n font-size: var(--smrt-typography-label-large-size, 0.875rem);\n font-weight: var(--smrt-typography-weight-medium, 500);\n cursor: pointer;\n border: 1px solid;\n transition: all 0.2s;\n }\n \n .cancel-btn {\n background: var(--smrt-color-surface, #fff);\n border-color: var(--smrt-color-outline-variant, #d1d5db);\n color: var(--smrt-color-on-surface, #374151);\n }\n\n .cancel-btn:hover:not(:disabled) {\n background: var(--smrt-color-surface-container-low, #f9fafb);\n }\n\n .submit-btn {\n background: var(--smrt-color-primary, #3b82f6);\n border-color: var(--smrt-color-primary, #3b82f6);\n color: var(--smrt-color-on-primary, white);\n }\n\n .submit-btn:hover:not(:disabled) {\n background: var(--smrt-color-primary, #2563eb);\n }\n \n .submit-btn:disabled, .cancel-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n</style>"],"names":["root","root_1","root_2","root_3","$$anchor"],"mappings":"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"}