@happyvertical/smrt-assets 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,8 +1,8 @@
1
1
  {
2
2
  "version": "1.0.0",
3
- "timestamp": 1782257824701,
3
+ "timestamp": 1782278439359,
4
4
  "packageName": "@happyvertical/smrt-assets",
5
- "packageVersion": "0.34.4",
5
+ "packageVersion": "0.34.6",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-assets:AssetAssociation": {
8
8
  "name": "assetassociation",
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "generatedAt": "2026-06-23T23:37:06.168Z",
3
+ "generatedAt": "2026-06-24T05:20:39.916Z",
4
4
  "packageName": "@happyvertical/smrt-assets",
5
- "packageVersion": "0.34.4",
5
+ "packageVersion": "0.34.6",
6
6
  "sourceManifestPath": "dist/manifest.json",
7
7
  "agentDocPath": "AGENTS.md",
8
8
  "sourceHashes": {
9
- "manifest": "d940ee88361833c65d3a3ba0423c40359dccc8552cf4303c1361f9673252af5f",
10
- "packageJson": "f5ca4940cf312dfdb2d89b163b549015037db829728dba81546e13ca3d230479",
9
+ "manifest": "37c93b8225560c459942aecd64dc56cdddba2763dcfb4d1533fd23ea6155aa5c",
10
+ "packageJson": "fbb530de68a6cc8e154c7d6a4a61eb98d83387b740abf0b2fedb55cf7410c729",
11
11
  "agents": "a034545874fb7767b31168d98aa2b1b8cac205b14f2f04fb5a8e5acf33690eef"
12
12
  },
13
13
  "exports": [
@@ -8,6 +8,7 @@
8
8
 
9
9
  import { ConfirmDialog } from '@happyvertical/smrt-ui/feedback';
10
10
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
11
+ import { Button } from '@happyvertical/smrt-ui/ui';
11
12
  import { M } from './i18n.js';
12
13
  import type { ActionBarProps } from './types';
13
14
 
@@ -56,34 +57,33 @@ const count = $derived(selectedAssets.length);
56
57
  <div class="action-bar">
57
58
  <div class="action-bar__left">
58
59
  <span class="action-bar__count">{count} selected</span>
59
- <button
60
- type="button"
61
- class="action-bar__clear"
60
+ <Button
61
+ variant="ghost"
62
+ size="sm"
62
63
  onclick={() => (onclearselection ?? onClearSelection)()}
63
64
  >
64
65
  Clear
65
- </button>
66
+ </Button>
66
67
  </div>
67
68
 
68
69
  <div class="action-bar__actions">
69
70
  {#each customActions as ca (ca.label)}
70
71
  {#if ca.multi !== false || count === 1}
71
- <button
72
- type="button"
73
- class="action-btn"
74
- class:action-btn--destructive={ca.destructive}
72
+ <Button
73
+ variant={ca.destructive ? 'danger' : 'secondary'}
74
+ size="sm"
75
75
  onclick={() => handleCustomAction(ca.action)}
76
76
  >
77
77
  {#if ca.icon}
78
78
  {@render ca.icon()}
79
79
  {/if}
80
80
  {ca.label}
81
- </button>
81
+ </Button>
82
82
  {/if}
83
83
  {/each}
84
84
 
85
85
  <!-- Default: Delete -->
86
- <button type="button" class="action-btn action-btn--destructive" onclick={handleDelete}>
86
+ <Button variant="danger" size="sm" onclick={handleDelete}>
87
87
  <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
88
88
  <polyline points="3 6 5 6 21 6"></polyline>
89
89
  <path d="M19 6l-2 14H7L5 6"></path>
@@ -92,7 +92,7 @@ const count = $derived(selectedAssets.length);
92
92
  <path d="M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2"></path>
93
93
  </svg>
94
94
  Delete
95
- </button>
95
+ </Button>
96
96
  </div>
97
97
  </div>
98
98
 
@@ -144,57 +144,12 @@ const count = $derived(selectedAssets.length);
144
144
  color: var(--smrt-color-on-primary-container, #002d6c);
145
145
  }
146
146
 
147
- .action-bar__clear {
148
- padding: var(--smrt-spacing-1, 4px) var(--smrt-spacing-2, 8px);
149
- border: none;
150
- background: transparent;
151
- font-family: inherit;
152
- font-size: var(--smrt-typography-body-medium-size, 0.875rem);
153
- color: var(--smrt-color-primary, #005ac1);
154
- cursor: pointer;
155
- border-radius: var(--smrt-radius-small, 0.25rem);
156
- }
157
-
158
- .action-bar__clear:hover {
159
- background: color-mix(in srgb, var(--smrt-color-shadow) 5%, transparent);
160
- }
161
-
162
147
  .action-bar__actions {
163
148
  display: flex;
164
149
  align-items: center;
165
150
  gap: var(--smrt-spacing-2, 0.5rem);
166
151
  }
167
152
 
168
- .action-btn {
169
- display: inline-flex;
170
- align-items: center;
171
- gap: var(--smrt-spacing-1, 4px);
172
- height: 32px;
173
- padding: 0 var(--smrt-spacing-3, 0.75rem);
174
- font-family: inherit;
175
- font-size: var(--smrt-typography-body-medium-size, 0.875rem);
176
- font-weight: var(--smrt-typography-weight-medium, 500);
177
- border: 1px solid var(--smrt-color-outline-variant, #e5e7eb);
178
- background: var(--smrt-color-surface, #ffffff);
179
- color: var(--smrt-color-on-surface, #111827);
180
- border-radius: var(--smrt-radius-medium, 0.5rem);
181
- cursor: pointer;
182
- transition: all 150ms ease;
183
- }
184
-
185
- .action-btn:hover {
186
- box-shadow: var(--smrt-elevation-1, 0 1px 2px rgba(0,0,0,0.05));
187
- }
188
-
189
- .action-btn--destructive {
190
- border-color: var(--smrt-color-error, #dc2626);
191
- color: var(--smrt-color-error, #dc2626);
192
- }
193
-
194
- .action-btn--destructive:hover {
195
- background: var(--smrt-color-error-container, #fef2f2);
196
- }
197
-
198
153
  @media (prefers-reduced-motion: reduce) {
199
154
  .action-bar {
200
155
  animation: none;
@@ -1 +1 @@
1
- {"version":3,"file":"ActionBar.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/ActionBar.svelte.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAmG9C,QAAA,MAAM,SAAS,oDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"ActionBar.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/ActionBar.svelte.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAoG9C,QAAA,MAAM,SAAS,oDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -261,18 +261,18 @@ function formatDate(date: Date | string | undefined): string {
261
261
  <section class="detail__section">
262
262
  <h3 class="section-heading">{t(M['assets.asset_detail.quick_actions'])}</h3>
263
263
  <div class="quick-actions">
264
- <button type="button" class="quick-btn" onclick={copyUrl} disabled={!asset.sourceUri}>
264
+ <Button variant="ghost" size="sm" class="quick-btn" onclick={copyUrl} disabled={!asset.sourceUri}>
265
265
  {t(M['assets.asset_detail.copy_url'])}
266
- </button>
266
+ </Button>
267
267
  {#if isImage}
268
- <button type="button" class="quick-btn" onclick={copyMarkdown} disabled={!asset.sourceUri}>
268
+ <Button variant="ghost" size="sm" class="quick-btn" onclick={copyMarkdown} disabled={!asset.sourceUri}>
269
269
  {t(M['assets.asset_detail.copy_markdown'])}
270
- </button>
270
+ </Button>
271
271
  {/if}
272
272
  {#if onedit && isImage}
273
- <button type="button" class="quick-btn" onclick={handleEdit}>
273
+ <Button variant="ghost" size="sm" class="quick-btn" onclick={handleEdit}>
274
274
  {t(M['assets.asset_detail.edit_image'])}
275
- </button>
275
+ </Button>
276
276
  {/if}
277
277
  </div>
278
278
  <div class="copy-feedback" role="status" aria-live="polite">{copyFeedback}</div>
@@ -462,33 +462,25 @@ function formatDate(date: Date | string | undefined): string {
462
462
  gap: var(--smrt-spacing-2, 0.5rem);
463
463
  }
464
464
 
465
- .quick-btn {
466
- display: inline-flex;
467
- align-items: center;
465
+ /* The quick-action buttons render via <Button> (issue #1589). They keep a
466
+ bespoke bordered-surface look (vs. the transparent ghost variant), so the
467
+ overrides reach the child-rendered <button> through :global() scoping. */
468
+ .quick-actions :global(.quick-btn) {
468
469
  gap: var(--smrt-spacing-1, 4px);
469
470
  height: 32px;
470
471
  padding: 0 var(--smrt-spacing-3, 0.75rem);
471
- font-family: inherit;
472
472
  font-size: var(--smrt-typography-label-medium-size, 0.8rem);
473
473
  font-weight: var(--smrt-typography-weight-medium, 500);
474
474
  border: 1px solid var(--smrt-color-outline-variant, #e5e7eb);
475
475
  background: var(--smrt-color-surface, #ffffff);
476
476
  color: var(--smrt-color-on-surface, #111827);
477
- border-radius: var(--smrt-radius-medium, 0.5rem);
478
- cursor: pointer;
479
- transition: all 150ms ease;
480
477
  }
481
478
 
482
- .quick-btn:hover:not(:disabled) {
479
+ .quick-actions :global(.quick-btn:hover:not(:disabled)) {
483
480
  background: var(--smrt-color-surface-container-low, #f9fafb);
484
481
  box-shadow: var(--smrt-elevation-1);
485
482
  }
486
483
 
487
- .quick-btn:disabled {
488
- opacity: 0.5;
489
- cursor: not-allowed;
490
- }
491
-
492
484
  .copy-feedback {
493
485
  margin-top: var(--smrt-spacing-2, 0.5rem);
494
486
  font-size: var(--smrt-typography-label-medium-size, 0.8rem);
@@ -107,6 +107,7 @@ function getAltText(asset: PersistedAsset): string {
107
107
  inside an interactive control (axe nested-interactive). It sits
108
108
  above the non-interactive content but below the checkbox (z-index),
109
109
  and is keyboard-activatable natively (Enter/Space). -->
110
+ <!-- raw-primitive-allow: stretched transparent click-catching card overlay positioned absolute inset 0, layered under the checkbox by z-index; not a styled action button -->
110
111
  <button
111
112
  type="button"
112
113
  class="asset-card__open"
@@ -1 +1 @@
1
- {"version":3,"file":"AssetGrid.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/AssetGrid.svelte.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,SAAS,CAAC;AA+I9D,QAAA,MAAM,SAAS,oDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"AssetGrid.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/AssetGrid.svelte.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,SAAS,CAAC;AAgJ9D,QAAA,MAAM,SAAS,oDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -7,6 +7,7 @@
7
7
  */
8
8
 
9
9
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
10
+ import { Button } from '@happyvertical/smrt-ui/ui';
10
11
  import { M } from './i18n.js';
11
12
  import type {
12
13
  AssetListProps,
@@ -120,15 +121,15 @@ function setIndeterminate(node: HTMLInputElement, value: boolean) {
120
121
  </th>
121
122
  <th class="col-thumb">Preview</th>
122
123
  <th class="col-name">
123
- <button type="button" class="sort-btn" onclick={() => handleSort('name')}>
124
+ <Button variant="ghost" size="sm" class="sort-btn" onclick={() => handleSort('name')}>
124
125
  Name <span class="sort-indicator">{getSortIndicator('name')}</span>
125
- </button>
126
+ </Button>
126
127
  </th>
127
128
  <th class="col-type">Type</th>
128
129
  <th class="col-date">
129
- <button type="button" class="sort-btn" onclick={() => handleSort('createdAt')}>
130
+ <Button variant="ghost" size="sm" class="sort-btn" onclick={() => handleSort('createdAt')}>
130
131
  Created <span class="sort-indicator">{getSortIndicator('createdAt')}</span>
131
- </button>
132
+ </Button>
132
133
  </th>
133
134
  <th class="col-status">Status</th>
134
135
  </tr>
@@ -187,15 +188,15 @@ function setIndeterminate(node: HTMLInputElement, value: boolean) {
187
188
  </td>
188
189
  <td class="col-name">
189
190
  <!-- The name is the row's open action (a button, not a
190
- role="button" on the <tr> nesting the checkbox avoids axe
191
+ role="button" on the row nesting the checkbox, which avoids axe
191
192
  nested-interactive). -->
192
- <button
193
- type="button"
193
+ <Button
194
+ variant="ghost"
194
195
  class="row-name"
195
196
  onclick={() => onAssetClick(asset)}
196
197
  >
197
198
  {asset.name || 'Untitled'}
198
- </button>
199
+ </Button>
199
200
  {#if asset.description}
200
201
  <span class="row-desc">{asset.description}</span>
201
202
  {/if}
@@ -308,7 +309,10 @@ function setIndeterminate(node: HTMLInputElement, value: boolean) {
308
309
  min-width: 150px;
309
310
  }
310
311
 
311
- .row-name {
312
+ /* The row name renders via <Button class="row-name"> (issue #1589). The
313
+ overrides reset it to inline name text and must reach the child-rendered
314
+ <button> through :global() scoping. */
315
+ .col-name :global(.row-name) {
312
316
  display: block;
313
317
  font-weight: var(--smrt-typography-weight-medium, 500);
314
318
  white-space: nowrap;
@@ -327,16 +331,10 @@ function setIndeterminate(node: HTMLInputElement, value: boolean) {
327
331
  cursor: pointer;
328
332
  }
329
333
 
330
- .row-name:hover {
334
+ .col-name :global(.row-name:hover) {
331
335
  text-decoration: underline;
332
336
  }
333
337
 
334
- .row-name:focus-visible {
335
- outline: 2px solid var(--smrt-color-primary, #005ac1);
336
- outline-offset: 2px;
337
- border-radius: var(--smrt-radius-small, 0.25rem);
338
- }
339
-
340
338
  .row-desc {
341
339
  display: block;
342
340
  font-size: var(--smrt-typography-body-small-size, 0.75rem);
@@ -383,10 +381,9 @@ function setIndeterminate(node: HTMLInputElement, value: boolean) {
383
381
  background: var(--smrt-color-success, #22c55e);
384
382
  }
385
383
 
386
- /* Sort */
387
- .sort-btn {
388
- display: inline-flex;
389
- align-items: center;
384
+ /* Sort — renders via <Button class="sort-btn"> (issue #1589). Overrides reset
385
+ it to an inline header-text button and reach the child <button> via :global(). */
386
+ .list-table__head :global(.sort-btn) {
390
387
  gap: var(--smrt-spacing-1, 4px);
391
388
  padding: 0;
392
389
  border: none;
@@ -394,10 +391,9 @@ function setIndeterminate(node: HTMLInputElement, value: boolean) {
394
391
  font: inherit;
395
392
  font-weight: var(--smrt-typography-weight-semibold, 600);
396
393
  color: inherit;
397
- cursor: pointer;
398
394
  }
399
395
 
400
- .sort-btn:hover {
396
+ .list-table__head :global(.sort-btn:hover) {
401
397
  color: var(--smrt-color-primary, #005ac1);
402
398
  }
403
399
 
@@ -1 +1 @@
1
- {"version":3,"file":"AssetList.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/AssetList.svelte.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,cAAc,EAIf,MAAM,SAAS,CAAC;AAkMjB,QAAA,MAAM,SAAS,oDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"AssetList.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/AssetList.svelte.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,cAAc,EAIf,MAAM,SAAS,CAAC;AAmMjB,QAAA,MAAM,SAAS,oDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -8,6 +8,7 @@ import { onDestroy } from 'svelte';
8
8
  */
9
9
 
10
10
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
11
+ import { Button } from '@happyvertical/smrt-ui/ui';
11
12
  import { M } from './i18n.js';
12
13
  import type {
13
14
  AssetFilters,
@@ -116,12 +117,12 @@ const views: { key: AssetViewMode; label: string; icon: string }[] = [
116
117
  aria-label={t(M['assets.asset_toolbar.search_assets'])}
117
118
  />
118
119
  {#if searchValue}
119
- <button type="button" class="search-clear" onclick={handleClearSearch} aria-label={t(M['assets.asset_toolbar.clear_search'])}>
120
+ <Button variant="ghost" size="sm" class="search-clear" onclick={handleClearSearch} aria-label={t(M['assets.asset_toolbar.clear_search'])}>
120
121
  <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
121
122
  <line x1="18" y1="6" x2="6" y2="18"></line>
122
123
  <line x1="6" y1="6" x2="18" y2="18"></line>
123
124
  </svg>
124
- </button>
125
+ </Button>
125
126
  {/if}
126
127
  </div>
127
128
 
@@ -148,10 +149,9 @@ const views: { key: AssetViewMode; label: string; icon: string }[] = [
148
149
  <!-- View Toggle -->
149
150
  <div class="view-toggle" role="group" aria-label={t(M['assets.asset_toolbar.view_mode'])}>
150
151
  {#each views as v (v.key)}
151
- <button
152
- type="button"
152
+ <Button
153
+ variant={view === v.key ? 'primary' : 'ghost'}
153
154
  class="view-toggle__btn"
154
- class:view-toggle__btn--active={view === v.key}
155
155
  onclick={() => (onviewchange ?? onViewChange)(v.key)}
156
156
  aria-label={t(M['assets.asset_toolbar.view_label'], { label: v.label })}
157
157
  aria-pressed={view === v.key}
@@ -173,13 +173,13 @@ const views: { key: AssetViewMode; label: string; icon: string }[] = [
173
173
  <line x1="3" y1="18" x2="3.01" y2="18"></line>
174
174
  </svg>
175
175
  {/if}
176
- </button>
176
+ </Button>
177
177
  {/each}
178
178
  </div>
179
179
 
180
180
  <!-- Upload Button -->
181
- <button
182
- type="button"
181
+ <Button
182
+ variant="primary"
183
183
  class="upload-btn"
184
184
  onclick={() => (onupload ?? onUpload)()}
185
185
  >
@@ -189,7 +189,7 @@ const views: { key: AssetViewMode; label: string; icon: string }[] = [
189
189
  <line x1="12" y1="3" x2="12" y2="15"></line>
190
190
  </svg>
191
191
  Upload
192
- </button>
192
+ </Button>
193
193
  </div>
194
194
  </div>
195
195
 
@@ -267,10 +267,10 @@ const views: { key: AssetViewMode; label: string; icon: string }[] = [
267
267
  display: none;
268
268
  }
269
269
 
270
- .search-clear {
271
- display: flex;
272
- align-items: center;
273
- justify-content: center;
270
+ /* search-clear renders via <Button class="search-clear"> (issue #1589). The
271
+ overrides shape it into a small round icon button and reach the child
272
+ <button> via :global() scoping. */
273
+ .asset-toolbar__search :global(.search-clear) {
274
274
  width: 24px;
275
275
  height: 24px;
276
276
  margin-right: var(--smrt-spacing-1, 0.25rem);
@@ -278,11 +278,10 @@ const views: { key: AssetViewMode; label: string; icon: string }[] = [
278
278
  border: none;
279
279
  background: transparent;
280
280
  color: var(--smrt-color-on-surface-variant, #6b7280);
281
- cursor: pointer;
282
281
  border-radius: var(--smrt-radius-full, 9999px);
283
282
  }
284
283
 
285
- .search-clear:hover {
284
+ .asset-toolbar__search :global(.search-clear:hover) {
286
285
  color: var(--smrt-color-on-surface, #111827);
287
286
  background: var(--smrt-color-surface-container, #f3f4f6);
288
287
  }
@@ -313,58 +312,32 @@ const views: { key: AssetViewMode; label: string; icon: string }[] = [
313
312
  overflow: hidden;
314
313
  }
315
314
 
316
- .view-toggle__btn {
317
- display: flex;
318
- align-items: center;
319
- justify-content: center;
315
+ /* view-toggle__btn renders via <Button> (issue #1589); the active state is the
316
+ `primary` variant, the inactive state the `ghost` variant. These overrides
317
+ give the buttons their square icon footprint and the segmented divider, and
318
+ reach the child <button> via :global() scoping. */
319
+ .view-toggle :global(.view-toggle__btn) {
320
320
  width: 36px;
321
321
  height: 36px;
322
322
  padding: 0;
323
323
  border: none;
324
- background: var(--smrt-color-surface, #ffffff);
325
- color: var(--smrt-color-on-surface-variant, #6b7280);
326
- cursor: pointer;
327
- transition: all 150ms ease;
324
+ border-radius: 0;
328
325
  }
329
326
 
330
- .view-toggle__btn:not(:last-child) {
327
+ .view-toggle :global(.view-toggle__btn:not(:last-child)) {
331
328
  border-right: 1px solid var(--smrt-color-outline-variant, #e5e7eb);
332
329
  }
333
330
 
334
- .view-toggle__btn:hover {
335
- background: var(--smrt-color-surface-container-low, #f9fafb);
336
- }
337
-
338
- .view-toggle__btn--active {
339
- background: var(--smrt-color-primary-container, #dbeafe);
340
- color: var(--smrt-color-on-primary-container, #002d6c);
341
- }
342
-
343
- /* Upload Button */
344
- .upload-btn {
345
- display: inline-flex;
346
- align-items: center;
331
+ /* Upload Button — renders via <Button variant="primary" class="upload-btn">
332
+ (issue #1589). The primary variant owns the fill/hover; the override only
333
+ pins the toolbar-matching 36px height and gap, reaching the child <button>
334
+ via :global() scoping. */
335
+ .asset-toolbar__right :global(.upload-btn) {
347
336
  gap: var(--smrt-spacing-1, 0.25rem);
348
337
  height: 36px;
349
338
  padding: 0 var(--smrt-spacing-3, 0.75rem);
350
- font-family: inherit;
351
339
  font-size: var(--smrt-typography-body-medium-size, 0.875rem);
352
340
  font-weight: var(--smrt-typography-weight-medium, 500);
353
- color: var(--smrt-color-on-primary, #ffffff);
354
- background: var(--smrt-color-primary, #005ac1);
355
- border: none;
356
- border-radius: var(--smrt-radius-medium, 0.5rem);
357
- cursor: pointer;
358
- transition: box-shadow 150ms ease;
359
- }
360
-
361
- .upload-btn:hover {
362
- box-shadow: var(--smrt-elevation-2, 0 1px 3px rgba(0,0,0,0.1));
363
- }
364
-
365
- .upload-btn:focus-visible {
366
- outline: 2px solid var(--smrt-color-primary, #005ac1);
367
- outline-offset: 2px;
368
341
  }
369
342
 
370
343
  @media (max-width: 640px) {
@@ -1 +1 @@
1
- {"version":3,"file":"AssetToolbar.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/AssetToolbar.svelte.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAIV,iBAAiB,EAElB,MAAM,SAAS,CAAC;AA4KjB,QAAA,MAAM,YAAY,uDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"AssetToolbar.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/AssetToolbar.svelte.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAIV,iBAAiB,EAElB,MAAM,SAAS,CAAC;AA6KjB,QAAA,MAAM,YAAY,uDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
@@ -184,9 +184,9 @@ const isLargeFile = $derived((file?.size ?? 0) > 2 * 1024 * 1024);
184
184
  <span class="file-preview__warning">{t(M['assets.create_asset_modal.large_file_warning'])}</span>
185
185
  {/if}
186
186
  </div>
187
- <button type="button" class="file-preview__remove" onclick={() => { file = null; }} aria-label={t(M['assets.create_asset_modal.remove_file'])}>
187
+ <Button variant="ghost" size="sm" class="file-preview__remove" onclick={() => { file = null; }} aria-label={t(M['assets.create_asset_modal.remove_file'])}>
188
188
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
189
- </button>
189
+ </Button>
190
190
  </div>
191
191
 
192
192
  <div class="form-fields">
@@ -332,10 +332,10 @@ const isLargeFile = $derived((file?.size ?? 0) > 2 * 1024 * 1024);
332
332
  margin-top: var(--smrt-spacing-1, 4px);
333
333
  }
334
334
 
335
- .file-preview__remove {
336
- display: flex;
337
- align-items: center;
338
- justify-content: center;
335
+ /* file-preview__remove renders via <Button class="file-preview__remove">
336
+ (issue #1589). The overrides shape it into a small round icon button and
337
+ reach the child <button> via :global() scoping. */
338
+ .file-preview :global(.file-preview__remove) {
339
339
  width: 28px;
340
340
  height: 28px;
341
341
  flex-shrink: 0;
@@ -343,11 +343,10 @@ const isLargeFile = $derived((file?.size ?? 0) > 2 * 1024 * 1024);
343
343
  border: none;
344
344
  background: transparent;
345
345
  color: var(--smrt-color-on-surface-variant, #6b7280);
346
- cursor: pointer;
347
346
  border-radius: var(--smrt-radius-full, 9999px);
348
347
  }
349
348
 
350
- .file-preview__remove:hover {
349
+ .file-preview :global(.file-preview__remove:hover) {
351
350
  background: var(--smrt-color-surface-container, #f3f4f6);
352
351
  color: var(--smrt-color-error, #dc2626);
353
352
  }
@@ -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 type { AssetDetailUpdates } from '../AssetDetail.svelte';
4
5
  import AssetDetail from '../AssetDetail.svelte';
5
6
  import { M } from '../i18n.js';
@@ -67,7 +68,7 @@ function handleEdit() {
67
68
  <p class="eyebrow">{t(M['assets.asset_detail_preview.modal_preview'])}</p>
68
69
  <h4>{previewAsset?.name ?? asset.name}</h4>
69
70
  <p>{t(M['assets.asset_detail_preview.description'])}</p>
70
- <button type="button" onclick={openPreview}>{t(M['assets.asset_detail_preview.open_asset_detail'])}</button>
71
+ <Button variant="primary" class="preview-open" onclick={openPreview}>{t(M['assets.asset_detail_preview.open_asset_detail'])}</Button>
71
72
  {#if statusMessage}
72
73
  <p class="status">{statusMessage}</p>
73
74
  {/if}
@@ -112,16 +113,15 @@ function handleEdit() {
112
113
  color: var(--smrt-color-primary, #0f766e);
113
114
  }
114
115
 
115
- button {
116
+ /* The open-preview button renders via <Button variant="primary"> (issue
117
+ #1589). The primary variant owns the fill/color; this override keeps the
118
+ pill shape and grid placement, reaching the child <button> via :global(). */
119
+ .preview-card :global(.preview-open) {
116
120
  justify-self: start;
117
121
  border: 0;
118
122
  border-radius: var(--smrt-radius-full, 9999px);
119
123
  padding: 0.75rem 1rem;
120
- font: inherit;
121
124
  font-weight: var(--smrt-typography-weight-semibold, 600);
122
- background: var(--smrt-color-primary, #0f766e);
123
- color: var(--smrt-color-on-primary, white);
124
- cursor: pointer;
125
125
  }
126
126
 
127
127
  .status {
@@ -1 +1 @@
1
- {"version":3,"file":"AssetDetailPreview.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/playground/AssetDetailPreview.svelte.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE9C,KAAK,gBAAgB,GAAI;IAAE,KAAK,EAAE,cAAc,CAAA;CAAE,CAAC;AAmFpD,QAAA,MAAM,kBAAkB,sDAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"AssetDetailPreview.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/playground/AssetDetailPreview.svelte.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE9C,KAAK,gBAAgB,GAAI;IAAE,KAAK,EAAE,cAAc,CAAA;CAAE,CAAC;AAoFpD,QAAA,MAAM,kBAAkB,sDAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,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 CreateAssetModal from '../CreateAssetModal.svelte';
4
5
  import { M } from '../i18n.js';
5
6
 
@@ -47,7 +48,7 @@ function handleCreate(data: {
47
48
  <p class="eyebrow">{t(M['assets.create_asset_modal_preview.modal_preview'])}</p>
48
49
  <h4>{t(M['assets.create_asset_modal_preview.title'])}</h4>
49
50
  <p>{t(M['assets.create_asset_modal_preview.description'])}</p>
50
- <button type="button" onclick={openPreview}>{t(M['assets.create_asset_modal_preview.open_upload_modal'])}</button>
51
+ <Button variant="primary" class="preview-open" onclick={openPreview}>{t(M['assets.create_asset_modal_preview.open_upload_modal'])}</Button>
51
52
 
52
53
  {#if statusMessage}
53
54
  <p class="status">{statusMessage}</p>
@@ -110,16 +111,15 @@ function handleCreate(data: {
110
111
  color: var(--smrt-color-primary, #0f766e);
111
112
  }
112
113
 
113
- button {
114
+ /* The open-modal button renders via <Button variant="primary"> (issue #1589).
115
+ The primary variant owns the fill/color; this override keeps the pill shape
116
+ and grid placement, reaching the child <button> via :global(). */
117
+ .preview-card :global(.preview-open) {
114
118
  justify-self: start;
115
119
  border: 0;
116
120
  border-radius: var(--smrt-radius-full, 9999px);
117
121
  padding: 0.75rem 1rem;
118
- font: inherit;
119
122
  font-weight: var(--smrt-typography-weight-semibold, 600);
120
- background: var(--smrt-color-primary, #0f766e);
121
- color: var(--smrt-color-on-primary, white);
122
- cursor: pointer;
123
123
  }
124
124
 
125
125
  .status {
@@ -1 +1 @@
1
- {"version":3,"file":"CreateAssetModalPreview.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/playground/CreateAssetModalPreview.svelte.ts"],"names":[],"mappings":"AA2FA,QAAA,MAAM,uBAAuB,2DAAwC,CAAC;AACtE,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAC1E,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"CreateAssetModalPreview.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/playground/CreateAssetModalPreview.svelte.ts"],"names":[],"mappings":"AA6FA,QAAA,MAAM,uBAAuB,2DAAwC,CAAC;AACtE,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAC1E,eAAe,uBAAuB,CAAC"}
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-assets",
3
- "version": "0.34.4",
3
+ "version": "0.34.6",
4
4
  "description": "Asset management system with versioning, metadata, and AI-powered operations for SMRT framework",
5
5
  "type": "module",
6
+ "smrtRawPrimitives": "strict-buttons",
6
7
  "main": "./dist/index.js",
7
8
  "types": "./dist/index.d.ts",
8
9
  "files": [
@@ -38,11 +39,11 @@
38
39
  "@happyvertical/logger": "^0.74.7",
39
40
  "@happyvertical/sql": "^0.74.7",
40
41
  "@happyvertical/utils": "^0.74.7",
41
- "@happyvertical/smrt-tenancy": "0.34.4",
42
- "@happyvertical/smrt-ui": "0.34.4",
43
- "@happyvertical/smrt-core": "0.34.4",
44
- "@happyvertical/smrt-tags": "0.34.4",
45
- "@happyvertical/smrt-types": "0.34.4"
42
+ "@happyvertical/smrt-core": "0.34.6",
43
+ "@happyvertical/smrt-tags": "0.34.6",
44
+ "@happyvertical/smrt-tenancy": "0.34.6",
45
+ "@happyvertical/smrt-types": "0.34.6",
46
+ "@happyvertical/smrt-ui": "0.34.6"
46
47
  },
47
48
  "peerDependencies": {
48
49
  "svelte": "^5.18.0"
@@ -64,8 +65,8 @@
64
65
  "typescript": "^5.9.3",
65
66
  "vite": "^7.3.1",
66
67
  "vitest": "^4.0.17",
67
- "@happyvertical/smrt-playground": "0.34.4",
68
- "@happyvertical/smrt-vitest": "0.34.4"
68
+ "@happyvertical/smrt-playground": "0.34.6",
69
+ "@happyvertical/smrt-vitest": "0.34.6"
69
70
  },
70
71
  "keywords": [
71
72
  "ai",