@x33025/sveltely 0.1.17 → 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/dist/actions/LoaderOverlay.svelte +33 -8
  2. package/dist/actions/LoaderOverlay.svelte.d.ts +3 -0
  3. package/dist/actions/loader.d.ts +3 -0
  4. package/dist/actions/loader.js +20 -7
  5. package/dist/components/Library/AnimatedNumber/AnimatedNumber.demo.svelte +3 -9
  6. package/dist/components/Library/ArticleEditor/ArticleEditor.svelte +3 -3
  7. package/dist/components/Library/ArticleEditor/ArticleEditorBody.svelte +59 -74
  8. package/dist/components/Library/ArticleEditor/ArticleEditorHeader.svelte +21 -31
  9. package/dist/components/Library/ArticleEditor/{ArticleBlockCode.svelte → Blocks/Code.svelte} +2 -3
  10. package/dist/components/Library/ArticleEditor/Blocks/Code.svelte.d.ts +8 -0
  11. package/dist/components/Library/ArticleEditor/{ArticleBlockFAQ.svelte → Blocks/FAQ.svelte} +3 -3
  12. package/dist/components/Library/ArticleEditor/Blocks/FAQ.svelte.d.ts +8 -0
  13. package/dist/components/Library/ArticleEditor/{ArticleBlockHeading.svelte → Blocks/Heading.svelte} +9 -9
  14. package/dist/components/Library/ArticleEditor/{ArticleBlockHeading.svelte.d.ts → Blocks/Heading.svelte.d.ts} +4 -4
  15. package/dist/components/Library/ArticleEditor/Blocks/Image.svelte +32 -0
  16. package/dist/components/Library/ArticleEditor/Blocks/Image.svelte.d.ts +10 -0
  17. package/dist/components/Library/ArticleEditor/{ArticleBlockList.svelte → Blocks/List.svelte} +4 -4
  18. package/dist/components/Library/ArticleEditor/{ArticleBlockList.svelte.d.ts → Blocks/List.svelte.d.ts} +4 -4
  19. package/dist/components/Library/ArticleEditor/{ArticleBlockParagraph.svelte → Blocks/Paragraph.svelte} +3 -3
  20. package/dist/components/Library/ArticleEditor/{ArticleBlockFallback.svelte.d.ts → Blocks/Paragraph.svelte.d.ts} +4 -4
  21. package/dist/components/Library/ArticleEditor/{ArticleBlockTable.svelte → Blocks/Table.svelte} +1 -1
  22. package/dist/components/Library/ArticleEditor/{ArticleBlockTable.svelte.d.ts → Blocks/Table.svelte.d.ts} +4 -4
  23. package/dist/components/Library/ArticleEditor/Blocks/index.d.ts +7 -0
  24. package/dist/components/Library/ArticleEditor/Blocks/index.js +7 -0
  25. package/dist/components/Library/ArticleEditor/index.d.ts +1 -9
  26. package/dist/components/Library/ArticleEditor/index.js +1 -9
  27. package/dist/components/Library/AsyncButton/AsyncButton.demo.svelte +2 -6
  28. package/dist/components/Library/AsyncButton/AsyncButton.svelte +9 -5
  29. package/dist/components/Library/AsyncButton/AsyncButton.svelte.d.ts +2 -1
  30. package/dist/components/Library/Button/Button.demo.svelte +2 -17
  31. package/dist/components/Library/Button/Button.demo.svelte.d.ts +0 -1
  32. package/dist/components/Library/Button/Button.svelte +15 -16
  33. package/dist/components/Library/Button/Button.svelte.d.ts +2 -1
  34. package/dist/components/Library/Calendar/Calendar.svelte +17 -27
  35. package/dist/components/Library/Checkbox/Checkbox.demo.svelte +7 -4
  36. package/dist/components/Library/Checkbox/Checkbox.svelte +24 -61
  37. package/dist/components/Library/Checkbox/Checkbox.svelte.d.ts +2 -4
  38. package/dist/components/Library/ChipInput/ChipInput.demo.svelte +2 -2
  39. package/dist/components/Library/ChipInput/ChipInput.svelte +7 -11
  40. package/dist/components/Library/ChipInput/ChipInput.svelte.d.ts +3 -2
  41. package/dist/components/Library/Dropdown/Action.svelte +1 -1
  42. package/dist/components/Library/Dropdown/Dropdown.demo.svelte +10 -10
  43. package/dist/components/Library/Dropdown/Dropdown.svelte +2 -6
  44. package/dist/components/Library/Dropdown/Item.svelte +2 -2
  45. package/dist/components/Library/Dropdown/Section.svelte +1 -1
  46. package/dist/components/Library/Dropdown/Trigger.svelte +3 -7
  47. package/dist/components/Library/Image/Image.demo.svelte +3 -3
  48. package/dist/components/Library/Image/Image.svelte +57 -12
  49. package/dist/components/Library/Image/Image.svelte.d.ts +1 -2
  50. package/dist/components/Library/Image/ImagePlaceholder.demo.svelte +12 -0
  51. package/dist/components/Library/Image/ImagePlaceholder.demo.svelte.d.ts +23 -0
  52. package/dist/components/Library/Image/ImagePlaceholder.svelte +28 -4
  53. package/dist/components/Library/Image/ImagePlaceholder.svelte.d.ts +1 -1
  54. package/dist/components/Library/Image/index.d.ts +1 -0
  55. package/dist/components/Library/Image/index.js +1 -0
  56. package/dist/components/Library/ImageMask/BrushPreview.svelte +6 -6
  57. package/dist/components/Library/ImageMask/ImageMask.demo.svelte +10 -8
  58. package/dist/components/Library/ImageMask/ImageMask.svelte +14 -6
  59. package/dist/components/Library/ImageMask/ImageMask.svelte.d.ts +1 -2
  60. package/dist/components/Library/ImageMask/MaskLayer.svelte +12 -6
  61. package/dist/components/Library/Label/Label.demo.svelte +9 -3
  62. package/dist/components/Library/Label/Label.svelte +8 -2
  63. package/dist/components/Library/Link/Link.svelte +10 -22
  64. package/dist/components/Library/Link/Link.svelte.d.ts +2 -3
  65. package/dist/components/Library/Loader/Loader.demo.svelte +9 -3
  66. package/dist/components/Library/NavigationStack/Link.svelte +8 -12
  67. package/dist/components/Library/NavigationStack/Link.svelte.d.ts +1 -3
  68. package/dist/components/Library/NavigationStack/SidebarToggle.svelte +8 -2
  69. package/dist/components/Library/NumberField/NumberField.svelte +21 -17
  70. package/dist/components/Library/NumberField/NumberField.svelte.d.ts +4 -2
  71. package/dist/components/Library/Pagination/Pagination.svelte +3 -3
  72. package/dist/components/Library/Popover/Popover.svelte +2 -7
  73. package/dist/components/Library/ScrollView/ScrollView.demo.svelte +50 -0
  74. package/dist/components/Library/ScrollView/ScrollView.demo.svelte.d.ts +10 -0
  75. package/dist/components/Library/ScrollView/ScrollView.svelte +414 -67
  76. package/dist/components/Library/ScrollView/ScrollView.svelte.d.ts +17 -1
  77. package/dist/components/Library/ScrollView/index.d.ts +1 -1
  78. package/dist/components/Library/SearchField/SearchField.demo.svelte +2 -2
  79. package/dist/components/Library/SearchField/SearchField.svelte +9 -4
  80. package/dist/components/Library/SearchField/SearchField.svelte.d.ts +2 -1
  81. package/dist/components/Library/SegmentedPicker/SegmentedPicker.demo.svelte +2 -2
  82. package/dist/components/Library/SegmentedPicker/SegmentedPicker.svelte +7 -7
  83. package/dist/components/Library/Sheet/Sheet.demo.svelte +1 -1
  84. package/dist/components/Library/Sheet/Sheet.svelte +2 -7
  85. package/dist/components/Library/Slider/Slider.demo.svelte +1 -1
  86. package/dist/components/Library/Slider/Slider.svelte +11 -7
  87. package/dist/components/Library/Slider/Slider.svelte.d.ts +2 -1
  88. package/dist/components/Library/Spinner/Spinner.demo.svelte +1 -1
  89. package/dist/components/Library/Switch/Switch.demo.svelte +7 -4
  90. package/dist/components/Library/Switch/Switch.svelte +28 -68
  91. package/dist/components/Library/Switch/Switch.svelte.d.ts +2 -4
  92. package/dist/components/Library/Table/Column.svelte +81 -0
  93. package/dist/components/Library/Table/Column.svelte.d.ts +39 -0
  94. package/dist/components/Library/Table/Table.demo.svelte +148 -0
  95. package/dist/components/Library/Table/Table.demo.svelte.d.ts +10 -0
  96. package/dist/components/Library/Table/Table.svelte +624 -0
  97. package/dist/components/Library/Table/Table.svelte.d.ts +42 -0
  98. package/dist/components/Library/Table/context.d.ts +5 -0
  99. package/dist/components/Library/Table/context.js +2 -0
  100. package/dist/components/Library/Table/index.js +5 -0
  101. package/dist/components/Library/Table/types.d.ts +37 -0
  102. package/dist/components/Library/Table/types.js +1 -0
  103. package/dist/components/Library/Text/Text.demo.svelte +21 -0
  104. package/dist/components/Library/Text/Text.demo.svelte.d.ts +24 -0
  105. package/dist/components/Library/Text/Text.svelte +41 -0
  106. package/dist/components/Library/Text/Text.svelte.d.ts +9 -0
  107. package/dist/components/Library/Text/index.d.ts +1 -0
  108. package/dist/components/Library/Text/index.js +1 -0
  109. package/dist/components/Library/TextEditor/TextEditor.svelte +15 -9
  110. package/dist/components/Library/TextEditor/TextEditor.svelte.d.ts +2 -4
  111. package/dist/components/Library/TextField/TextField.demo.svelte +1 -1
  112. package/dist/components/Library/TextField/TextField.svelte +21 -18
  113. package/dist/components/Library/TextField/TextField.svelte.d.ts +4 -2
  114. package/dist/components/Library/TextShimmer/TextShimmer.demo.svelte +1 -1
  115. package/dist/components/Library/TimePicker/TimePicker.demo.svelte +10 -2
  116. package/dist/components/Library/TimePicker/TimePicker.svelte +10 -5
  117. package/dist/components/Library/TokenSearchField/TokenSearchField.demo.svelte +4 -2
  118. package/dist/components/Library/TokenSearchField/TokenSearchField.svelte +11 -11
  119. package/dist/components/Library/TokenSearchField/TokenSearchField.svelte.d.ts +2 -1
  120. package/dist/components/Library/WheelPicker/WheelColumn.svelte +183 -126
  121. package/dist/components/Library/WheelPicker/WheelPicker.svelte +4 -4
  122. package/dist/components/Library/WheelPicker/WheelPicker.svelte.d.ts +2 -2
  123. package/dist/components/Library/WheelPicker/index.d.ts +1 -1
  124. package/dist/components/Library/WheelPicker/types.d.ts +6 -0
  125. package/dist/components/Local/ColorStyleControls.svelte +201 -0
  126. package/dist/components/Local/ColorStyleControls.svelte.d.ts +13 -0
  127. package/dist/components/Local/HeroCard.svelte +3 -3
  128. package/dist/components/Local/LayoutStyleControls.svelte +67 -0
  129. package/dist/components/Local/LayoutStyleControls.svelte.d.ts +11 -0
  130. package/dist/components/Local/StyleControls.svelte +48 -124
  131. package/dist/components/Local/StyleControls.svelte.d.ts +7 -5
  132. package/dist/index.d.ts +9 -2
  133. package/dist/index.js +5 -1
  134. package/dist/style/index.css +7 -12
  135. package/dist/style/label.d.ts +2 -1
  136. package/dist/style/label.js +2 -1
  137. package/dist/style/surface.js +4 -0
  138. package/dist/style/text-editor.d.ts +2 -13
  139. package/dist/style/text-editor.js +1 -12
  140. package/dist/style/text.d.ts +26 -0
  141. package/dist/style/text.js +69 -0
  142. package/dist/style/tooltip.d.ts +4 -0
  143. package/dist/style/tooltip.js +1 -0
  144. package/dist/style.css +41 -114
  145. package/package.json +1 -1
  146. package/dist/components/Library/ArticleEditor/ArticleBlockCode.svelte.d.ts +0 -8
  147. package/dist/components/Library/ArticleEditor/ArticleBlockFAQ.svelte.d.ts +0 -8
  148. package/dist/components/Library/ArticleEditor/ArticleBlockFallback.svelte +0 -79
  149. package/dist/components/Library/ArticleEditor/ArticleBlockImage.svelte +0 -48
  150. package/dist/components/Library/ArticleEditor/ArticleBlockImage.svelte.d.ts +0 -9
  151. package/dist/components/Library/ArticleEditor/ArticleBlockParagraph.svelte.d.ts +0 -15
  152. package/dist/components/Library/ArticleEditor/ArticleImagePreview.svelte +0 -71
  153. package/dist/components/Library/ArticleEditor/ArticleImagePreview.svelte.d.ts +0 -8
@@ -2,7 +2,9 @@
2
2
  import type { Snippet } from 'svelte';
3
3
  import { tick } from 'svelte';
4
4
  import { Plus } from '@lucide/svelte';
5
+ import { tooltip as tooltipAction } from '../../../actions/tooltip';
5
6
  import { extractStyleProps, surfaceStyle, type StyleProps } from '../../../style/surface';
7
+ import type { TooltipProps } from '../../../style/tooltip';
6
8
 
7
9
  type Props = {
8
10
  placeholder?: string;
@@ -11,6 +13,7 @@
11
13
  disabled?: boolean;
12
14
  action?: Snippet;
13
15
  } & StyleProps &
16
+ TooltipProps &
14
17
  Record<string, unknown>;
15
18
 
16
19
  let {
@@ -19,6 +22,7 @@
19
22
  selection = $bindable<string[] | undefined>(),
20
23
  disabled = false,
21
24
  action,
25
+ tooltip,
22
26
  ...restProps
23
27
  }: Props = $props();
24
28
 
@@ -248,6 +252,7 @@
248
252
  style={rootStyle}
249
253
  class:chip-input-disabled={disabled}
250
254
  aria-disabled={disabled}
255
+ use:tooltipAction={tooltip}
251
256
  {...props}
252
257
  >
253
258
  {#each tags as tag, index (tag)}
@@ -332,7 +337,7 @@
332
337
  box-sizing: border-box;
333
338
  border: 1px solid var(--sveltely-border-color);
334
339
  border-radius: var(--sveltely-border-radius);
335
- background: var(--sveltely-inactive-color);
340
+ background: var(--sveltely-control-inactive-color);
336
341
  color: black;
337
342
  min-height: var(--chip-input-control-height);
338
343
  padding: var(--chip-input-padding-y) var(--chip-input-padding-x);
@@ -345,13 +350,8 @@
345
350
  border-color: var(--sveltely-border-color);
346
351
  }
347
352
 
348
- .chip:hover,
349
353
  .chip-hovered {
350
- background: var(--sveltely-hover-color);
351
- }
352
-
353
- .chip-input-field:hover {
354
- background: var(--sveltely-hover-color);
354
+ background: color-mix(in oklab, var(--sveltely-control-active-color) 5%, transparent);
355
355
  }
356
356
 
357
357
  .chip-input-disabled {
@@ -363,10 +363,6 @@
363
363
  opacity: 0.5;
364
364
  }
365
365
 
366
- .chip-input-disabled .chip:hover {
367
- background: var(--sveltely-hover-color);
368
- }
369
-
370
366
  .chip-input-action {
371
367
  padding: 0;
372
368
  width: var(--chip-input-control-height);
@@ -1,12 +1,13 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  import { type StyleProps } from '../../../style/surface';
3
+ import type { TooltipProps } from '../../../style/tooltip';
3
4
  type Props = {
4
5
  placeholder?: string;
5
6
  tags: string[];
6
7
  selection?: string[];
7
8
  disabled?: boolean;
8
9
  action?: Snippet;
9
- } & StyleProps & Record<string, unknown>;
10
- declare const ChipInput: import("svelte").Component<Props, {}, "tags" | "selection">;
10
+ } & StyleProps & TooltipProps & Record<string, unknown>;
11
+ declare const ChipInput: import("svelte").Component<Props, {}, "selection" | "tags">;
11
12
  type ChipInput = ReturnType<typeof ChipInput>;
12
13
  export default ChipInput;
@@ -50,7 +50,7 @@
50
50
  }
51
51
 
52
52
  .dropdown-action:hover {
53
- background: var(--sveltely-hover-color);
53
+ background: color-mix(in oklab, var(--sveltely-control-active-color) 5%, transparent);
54
54
  }
55
55
 
56
56
  .dropdown-action:disabled {
@@ -89,7 +89,7 @@
89
89
 
90
90
  <div class="grid w-full gap-4 md:grid-cols-2">
91
91
  <div class="vstack gap-2">
92
- <p class="text-sm font-medium text-[var(--sveltely-primary-color)]">Default trigger</p>
92
+ <p class="text-sm font-medium text-[var(--sveltely-text-primary-color)]">Default trigger</p>
93
93
  <Dropdown bind:value={status} placeholder="Choose status" selectedLabel={selectedStatusLabel}>
94
94
  <Dropdown.Section label="Publishing">
95
95
  <Dropdown.Item value="draft">Draft</Dropdown.Item>
@@ -103,13 +103,13 @@
103
103
  <Dropdown.Item value="private" disabled>Private</Dropdown.Item>
104
104
  </Dropdown.Section>
105
105
  </Dropdown>
106
- <p class="text-xs text-[var(--sveltely-secondary-color)]">
106
+ <p class="text-xs text-[var(--sveltely-text-secondary-color)]">
107
107
  Selected: {selectedStatusLabel ?? 'none'}
108
108
  </p>
109
109
  </div>
110
110
 
111
111
  <div class="vstack gap-2">
112
- <p class="text-sm font-medium text-[var(--sveltely-primary-color)]">
112
+ <p class="text-sm font-medium text-[var(--sveltely-text-primary-color)]">
113
113
  Custom trigger and rich rows
114
114
  </p>
115
115
  <Dropdown
@@ -121,17 +121,17 @@
121
121
  <Dropdown.Trigger>
122
122
  {#if selectedWebsite}
123
123
  <span class="hstack min-w-0 items-center gap-2">
124
- <span class="truncate text-[var(--sveltely-primary-color)]"
124
+ <span class="truncate text-[var(--sveltely-text-primary-color)]"
125
125
  >{selectedWebsite.name}</span
126
126
  >
127
127
  {#if selectedWebsite.domain}
128
- <span class="truncate text-xs text-[var(--sveltely-secondary-color)]">
128
+ <span class="truncate text-xs text-[var(--sveltely-text-secondary-color)]">
129
129
  {selectedWebsite.domain}
130
130
  </span>
131
131
  {/if}
132
132
  </span>
133
133
  {:else}
134
- <span class="text-[var(--sveltely-secondary-color)]">Select website</span>
134
+ <span class="text-[var(--sveltely-text-secondary-color)]">Select website</span>
135
135
  {/if}
136
136
  </Dropdown.Trigger>
137
137
  {/snippet}
@@ -148,7 +148,7 @@
148
148
  </Dropdown.Item>
149
149
  <Dropdown.Section label="Websites">
150
150
  {#if filteredWebsites.length === 0}
151
- <div class="px-2 py-1 text-sm text-[var(--sveltely-secondary-color)]">
151
+ <div class="px-2 py-1 text-sm text-[var(--sveltely-text-secondary-color)]">
152
152
  No websites found.
153
153
  </div>
154
154
  {:else}
@@ -166,7 +166,7 @@
166
166
  <div class="vstack min-w-0 gap-0.5">
167
167
  <span class="truncate">{website.name}</span>
168
168
  {#if website.domain}
169
- <span class="truncate text-xs text-[var(--sveltely-secondary-color)]"
169
+ <span class="truncate text-xs text-[var(--sveltely-text-secondary-color)]"
170
170
  >{website.domain}</span
171
171
  >
172
172
  {/if}
@@ -174,7 +174,7 @@
174
174
  {#if selected}
175
175
  <CheckIcon
176
176
  size={14}
177
- class="shrink-0 text-[var(--sveltely-primary-color)]"
177
+ class="shrink-0 text-[var(--sveltely-text-primary-color)]"
178
178
  />
179
179
  {/if}
180
180
  {/snippet}
@@ -186,6 +186,6 @@
186
186
  {/if}
187
187
  </Dropdown.Section>
188
188
  </Dropdown>
189
- <p class="text-xs text-[var(--sveltely-secondary-color)]">Actions clicked: {actionCount}</p>
189
+ <p class="text-xs text-[var(--sveltely-text-secondary-color)]">Actions clicked: {actionCount}</p>
190
190
  </div>
191
191
  </div>
@@ -121,7 +121,7 @@
121
121
  onclick={triggerState.toggle}
122
122
  >
123
123
  <span class="dropdown-trigger-label">{triggerState.selectedLabel}</span>
124
- <ChevronDownIcon class="size-4 text-[var(--sveltely-secondary-color)]" />
124
+ <ChevronDownIcon class="size-4 text-[var(--sveltely-text-secondary-color)]" />
125
125
  </button>
126
126
  {/if}
127
127
  {/snippet}
@@ -151,7 +151,7 @@
151
151
  border: 1px solid var(--sveltely-border-color);
152
152
  border-radius: var(--sveltely-border-radius);
153
153
  background: var(--sveltely-background-color);
154
- color: var(--sveltely-primary-color);
154
+ color: var(--sveltely-text-primary-color);
155
155
  gap: var(--sveltely-gap);
156
156
  padding: calc(var(--sveltely-padding-y) * 0.67) var(--sveltely-padding-x);
157
157
  font-size: 0.875rem;
@@ -174,10 +174,6 @@
174
174
  flex: 0 0 auto;
175
175
  }
176
176
 
177
- .dropdown-trigger:hover {
178
- background: var(--sveltely-hover-color);
179
- }
180
-
181
177
  .dropdown-content {
182
178
  --dropdown-item-padding-x: calc(var(--sveltely-padding-x) * 0.67);
183
179
  --dropdown-item-padding-y: calc(var(--sveltely-padding-y) * 0.33);
@@ -41,7 +41,7 @@
41
41
  })}
42
42
  {/if}
43
43
  {#if resolvedShowCheck && selected}
44
- <CheckIcon class="dropdown-item-check size-4 text-[var(--sveltely-primary-color)]" />
44
+ <CheckIcon class="dropdown-item-check size-4 text-[var(--sveltely-text-primary-color)]" />
45
45
  {/if}
46
46
  </button>
47
47
 
@@ -58,7 +58,7 @@
58
58
  }
59
59
 
60
60
  .dropdown-item:hover {
61
- background: var(--sveltely-hover-color);
61
+ background: color-mix(in oklab, var(--sveltely-control-active-color) 5%, transparent);
62
62
  }
63
63
 
64
64
  .dropdown-item:disabled {
@@ -26,7 +26,7 @@
26
26
  .dropdown-section-label {
27
27
  padding-inline: 0.25rem;
28
28
  padding-top: 0.25rem;
29
- color: var(--sveltely-secondary-color);
29
+ color: var(--sveltely-text-secondary-color);
30
30
  font-size: 0.75rem;
31
31
  line-height: 1rem;
32
32
  font-weight: 500;
@@ -29,7 +29,7 @@
29
29
  {dropdown.selectedLabel}
30
30
  {/if}
31
31
  </span>
32
- <ChevronDownIcon class="size-4 text-[var(--sveltely-secondary-color)]" />
32
+ <ChevronDownIcon class="size-4 text-[var(--sveltely-text-secondary-color)]" />
33
33
  </button>
34
34
 
35
35
  <style>
@@ -40,8 +40,8 @@
40
40
  align-items: center;
41
41
  border: 1px solid var(--sveltely-border-color);
42
42
  border-radius: var(--sveltely-border-radius);
43
- background: var(--sveltely-background-color);
44
- color: var(--sveltely-primary-color);
43
+ background: var(--sveltely-control-background-color);
44
+ color: var(--sveltely-text-primary-color);
45
45
  gap: var(--sveltely-gap);
46
46
  padding: calc(var(--sveltely-padding-y) * 0.67) var(--sveltely-padding-x);
47
47
  font-size: 0.875rem;
@@ -64,8 +64,4 @@
64
64
  .dropdown-trigger :global(svg) {
65
65
  flex: 0 0 auto;
66
66
  }
67
-
68
- .dropdown-trigger:hover {
69
- background: var(--sveltely-hover-color);
70
- }
71
67
  </style>
@@ -1,7 +1,7 @@
1
1
  <script module lang="ts">
2
2
  export const demo = {
3
3
  name: 'Image',
4
- description: 'Responsive image display with generated placeholder and busy states.'
4
+ description: 'Responsive image display with icon placeholder and busy states.'
5
5
  };
6
6
  </script>
7
7
 
@@ -13,6 +13,6 @@
13
13
  src="https://images.unsplash.com/photo-1542291026-7eec264c27ff?auto=format&fit=crop&w=600&q=80"
14
14
  alt="Red sneaker"
15
15
  fit="cover"
16
- class="aspect-square"
16
+ aspectRatio="1 / 1"
17
17
  />
18
- <Image busy placeholderKey="image-demo-loading" class="aspect-square" />
18
+ <Image busy aspectRatio="1 / 1" />
@@ -1,19 +1,19 @@
1
1
  <script lang="ts">
2
+ import { ImageOffIcon } from '@lucide/svelte';
2
3
  import type { Snippet } from 'svelte';
3
4
  import type { HTMLImgAttributes } from 'svelte/elements';
5
+ import { loader as loaderAction } from '../../../actions/loader';
4
6
  import type { ImageFit, ImageLoading } from '../../../style/media';
5
- import ImagePlaceholder from './ImagePlaceholder.svelte';
6
7
 
7
8
  type Props = {
8
9
  src?: string | null;
9
10
  alt?: string;
10
11
  fit?: ImageFit;
11
12
  busy?: boolean;
12
- placeholderKey?: string;
13
13
  loading?: ImageLoading;
14
14
  decoding?: HTMLImgAttributes['decoding'];
15
+ aspectRatio?: string;
15
16
  children?: Snippet;
16
- class?: string;
17
17
  };
18
18
 
19
19
  let {
@@ -21,28 +21,57 @@
21
21
  alt = '',
22
22
  fit = 'contain',
23
23
  busy = false,
24
- placeholderKey = 'default',
25
24
  loading = 'lazy',
26
25
  decoding = 'async',
27
- children,
28
- class: className = ''
26
+ aspectRatio,
27
+ children
29
28
  }: Props = $props();
30
29
 
31
- const showImage = $derived(Boolean(src) && !busy);
30
+ let imageLoaded = $state(false);
31
+ let imageFailed = $state(false);
32
+
33
+ $effect(() => {
34
+ src;
35
+ busy;
36
+ imageLoaded = false;
37
+ imageFailed = false;
38
+ });
39
+
40
+ const canRenderImage = $derived(Boolean(src) && !busy && !imageFailed);
41
+ const showLoader = $derived(busy || (Boolean(src) && !imageLoaded && !imageFailed));
42
+ const showMissingImage = $derived(!showLoader && (!src || imageFailed));
32
43
  </script>
33
44
 
34
- <div class={`image relative overflow-hidden bg-zinc-100 ${className}`}>
35
- {#if showImage}
45
+ <div
46
+ class="image relative overflow-hidden bg-zinc-100"
47
+ style={aspectRatio ? `aspect-ratio: ${aspectRatio}; height: auto;` : ''}
48
+ use:loaderAction={{
49
+ loading: showLoader,
50
+ background: 'color-mix(in oklab, var(--sveltely-text-secondary-color) 8%, transparent)',
51
+ color: 'color-mix(in oklab, var(--sveltely-text-secondary-color) 72%, transparent)'
52
+ }}
53
+ >
54
+ {#if canRenderImage}
36
55
  <img
37
56
  {src}
38
57
  {alt}
39
58
  {loading}
40
59
  {decoding}
41
60
  draggable="false"
42
- class="absolute inset-0 size-full {fit === 'cover' ? 'object-cover' : 'object-contain'}"
61
+ class="absolute inset-0 size-full {fit === 'cover'
62
+ ? 'object-cover'
63
+ : 'object-contain'} {imageLoaded
64
+ ? 'opacity-100'
65
+ : 'opacity-0'} transition-opacity duration-150"
66
+ onload={() => (imageLoaded = true)}
67
+ onerror={() => (imageFailed = true)}
43
68
  />
44
- {:else}
45
- <ImagePlaceholder seed={placeholderKey} class="absolute inset-0" />
69
+ {/if}
70
+
71
+ {#if showMissingImage}
72
+ <div class="image-fallback" aria-hidden="true">
73
+ <ImageOffIcon strokeWidth={1.5} />
74
+ </div>
46
75
  {/if}
47
76
 
48
77
  {#if children}
@@ -52,6 +81,22 @@
52
81
 
53
82
  <style>
54
83
  .image {
84
+ width: 100%;
85
+ height: 100%;
55
86
  border-radius: var(--image-border-radius, var(--sveltely-border-radius));
56
87
  }
88
+
89
+ .image-fallback {
90
+ position: absolute;
91
+ inset: 0;
92
+ display: grid;
93
+ place-items: center;
94
+ background: color-mix(in oklab, var(--sveltely-text-secondary-color) 8%, transparent);
95
+ color: color-mix(in oklab, var(--sveltely-text-secondary-color) 72%, transparent);
96
+ }
97
+
98
+ .image-fallback :global(svg) {
99
+ width: clamp(3rem, 18%, 7rem);
100
+ height: clamp(3rem, 18%, 7rem);
101
+ }
57
102
  </style>
@@ -6,11 +6,10 @@ type Props = {
6
6
  alt?: string;
7
7
  fit?: ImageFit;
8
8
  busy?: boolean;
9
- placeholderKey?: string;
10
9
  loading?: ImageLoading;
11
10
  decoding?: HTMLImgAttributes['decoding'];
11
+ aspectRatio?: string;
12
12
  children?: Snippet;
13
- class?: string;
14
13
  };
15
14
  declare const Image: import("svelte").Component<Props, {}, "">;
16
15
  type Image = ReturnType<typeof Image>;
@@ -0,0 +1,12 @@
1
+ <script module lang="ts">
2
+ export const demo = {
3
+ name: 'ImagePlaceholder',
4
+ description: 'Animated generated placeholder for custom image surfaces.'
5
+ };
6
+ </script>
7
+
8
+ <script lang="ts">
9
+ import { ImagePlaceholder } from './index';
10
+ </script>
11
+
12
+ <ImagePlaceholder seed="image-placeholder-demo" aspectRatio="4 / 3" />
@@ -0,0 +1,23 @@
1
+ export declare const demo: {
2
+ name: string;
3
+ description: string;
4
+ };
5
+ import { ImagePlaceholder } from './index';
6
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
7
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
8
+ $$bindings?: Bindings;
9
+ } & Exports;
10
+ (internal: unknown, props: {
11
+ $$events?: Events;
12
+ $$slots?: Slots;
13
+ }): Exports & {
14
+ $set?: any;
15
+ $on?: any;
16
+ };
17
+ z_$$bindings?: Bindings;
18
+ }
19
+ declare const ImagePlaceholder: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
20
+ [evt: string]: CustomEvent<any>;
21
+ }, {}, {}, string>;
22
+ type ImagePlaceholder = InstanceType<typeof ImagePlaceholder>;
23
+ export default ImagePlaceholder;
@@ -2,11 +2,11 @@
2
2
  import { onMount } from 'svelte';
3
3
 
4
4
  let {
5
- class: className = '',
6
- seed = 'default'
5
+ seed = 'default',
6
+ aspectRatio
7
7
  }: {
8
- class?: string;
9
8
  seed?: string;
9
+ aspectRatio?: string;
10
10
  } = $props();
11
11
 
12
12
  const fps = 24;
@@ -199,4 +199,28 @@
199
199
  });
200
200
  </script>
201
201
 
202
- <canvas bind:this={canvas} class={`block size-full ${className}`}></canvas>
202
+ <div
203
+ class="image-placeholder"
204
+ style={aspectRatio ? `aspect-ratio: ${aspectRatio}; height: auto;` : ''}
205
+ aria-hidden="true"
206
+ >
207
+ <canvas bind:this={canvas} class="image-placeholder-canvas"></canvas>
208
+ </div>
209
+
210
+ <style>
211
+ .image-placeholder {
212
+ position: relative;
213
+ width: 100%;
214
+ height: 100%;
215
+ overflow: hidden;
216
+ border-radius: var(--image-placeholder-border-radius, var(--sveltely-border-radius));
217
+ }
218
+
219
+ .image-placeholder-canvas {
220
+ position: absolute;
221
+ inset: 0;
222
+ display: block;
223
+ width: 100%;
224
+ height: 100%;
225
+ }
226
+ </style>
@@ -1,6 +1,6 @@
1
1
  type $$ComponentProps = {
2
- class?: string;
3
2
  seed?: string;
3
+ aspectRatio?: string;
4
4
  };
5
5
  declare const ImagePlaceholder: import("svelte").Component<$$ComponentProps, {}, "">;
6
6
  type ImagePlaceholder = ReturnType<typeof ImagePlaceholder>;
@@ -1 +1,2 @@
1
1
  export { default } from './Image.svelte';
2
+ export { default as ImagePlaceholder } from './ImagePlaceholder.svelte';
@@ -1 +1,2 @@
1
1
  export { default } from './Image.svelte';
2
+ export { default as ImagePlaceholder } from './ImagePlaceholder.svelte';
@@ -56,9 +56,9 @@
56
56
  pointer-events: none;
57
57
  border: 1.5px solid rgb(255 255 255 / 0.95);
58
58
  border-radius: 9999px;
59
- background: color-mix(in oklab, var(--sveltely-active-color) 16%, transparent);
59
+ background: color-mix(in oklab, var(--sveltely-control-active-color) 16%, transparent);
60
60
  box-shadow:
61
- 0 0 0 1px color-mix(in oklab, var(--sveltely-active-color) 90%, transparent),
61
+ 0 0 0 1px color-mix(in oklab, var(--sveltely-control-active-color) 90%, transparent),
62
62
  0 1px 4px rgb(0 0 0 / 0.22);
63
63
  will-change: transform, width, height;
64
64
  }
@@ -88,16 +88,16 @@
88
88
  box-sizing: border-box;
89
89
  border-radius: 9999px;
90
90
  border: 1.5px solid rgb(255 255 255 / 0.95);
91
- background: color-mix(in oklab, var(--sveltely-active-color) 20%, transparent);
91
+ background: color-mix(in oklab, var(--sveltely-control-active-color) 20%, transparent);
92
92
  box-shadow:
93
- 0 0 0 1px color-mix(in oklab, var(--sveltely-active-color) 95%, transparent),
93
+ 0 0 0 1px color-mix(in oklab, var(--sveltely-control-active-color) 95%, transparent),
94
94
  0 8px 24px rgb(0 0 0 / 0.24);
95
95
  }
96
96
 
97
97
  .brush-size-preview-label {
98
98
  border-radius: 9999px;
99
99
  background: rgb(255 255 255 / 0.88);
100
- color: var(--sveltely-primary-color);
100
+ color: var(--sveltely-text-primary-color);
101
101
  font-size: 0.75rem;
102
102
  font-weight: 650;
103
103
  line-height: 1;
@@ -113,7 +113,7 @@
113
113
  .brush-size-preview-erase .brush-size-preview-circle {
114
114
  background: rgb(255 255 255 / 0.2);
115
115
  box-shadow:
116
- 0 0 0 1px color-mix(in oklab, var(--sveltely-active-color) 85%, transparent),
116
+ 0 0 0 1px color-mix(in oklab, var(--sveltely-control-active-color) 85%, transparent),
117
117
  0 8px 24px rgb(0 0 0 / 0.24);
118
118
  }
119
119
  </style>
@@ -1,6 +1,6 @@
1
1
  <script module lang="ts">
2
2
  export const demo = {
3
- name: 'ImageMask',
3
+ name: 'Image Mask',
4
4
  description: 'Image mask editor that exposes the exported mask through bind:mask.',
5
5
  columnSpan: 2,
6
6
  rowSpan: 2
@@ -28,17 +28,19 @@
28
28
  bind:tool
29
29
  bind:clearRevision
30
30
  fit="cover"
31
- class="aspect-square"
31
+ aspectRatio="1 / 1"
32
32
  />
33
- <div class="vstack gap-2 text-sm text-[var(--sveltely-secondary-color)]">
34
- <div class="font-medium text-[var(--sveltely-primary-color)]">Mask</div>
33
+ <div class="vstack gap-2 text-sm text-[var(--sveltely-text-secondary-color)]">
34
+ <div class="font-medium text-[var(--sveltely-text-primary-color)]">Mask</div>
35
35
  <div class="aspect-square overflow-hidden rounded-md border border-zinc-200 bg-black">
36
36
  {#if mask}
37
37
  <img src={mask.dataUrl} alt="Exported mask" class="size-full object-contain" />
38
38
  {/if}
39
39
  </div>
40
40
  <label class="vstack gap-2 bg-white p-3">
41
- <span class="font-medium text-[var(--sveltely-primary-color)]">Brush size {brushSize}px</span>
41
+ <span class="font-medium text-[var(--sveltely-text-primary-color)]"
42
+ >Brush size {brushSize}px</span
43
+ >
42
44
  <Slider bind:value={brushSize} min={6} max={72} step={1} />
43
45
  <div class="image-mask-controls">
44
46
  <button
@@ -97,7 +99,7 @@
97
99
  align-items: center;
98
100
  justify-content: center;
99
101
  border-radius: 9999px;
100
- color: var(--sveltely-secondary-color);
102
+ color: var(--sveltely-text-secondary-color);
101
103
  transition:
102
104
  background-color 150ms,
103
105
  color 150ms,
@@ -106,8 +108,8 @@
106
108
 
107
109
  .image-mask-controls button:hover:not(:disabled),
108
110
  .image-mask-controls button.active {
109
- background: var(--sveltely-active-color);
110
- color: var(--sveltely-background-color);
111
+ background: var(--sveltely-control-active-color);
112
+ color: var(--sveltely-control-background-color);
111
113
  }
112
114
 
113
115
  .image-mask-controls button:disabled {
@@ -11,13 +11,12 @@
11
11
  fit = 'contain',
12
12
  busy = false,
13
13
  disabled = false,
14
- placeholderKey = 'default',
15
14
  loading = 'lazy',
16
15
  brushSize = $bindable(24),
17
16
  tool = $bindable<MaskTool>('paint'),
18
17
  clearRevision = $bindable(0),
19
18
  exportSize = 2048,
20
- class: className = ''
19
+ aspectRatio
21
20
  }: {
22
21
  src?: string | null;
23
22
  alt?: string;
@@ -25,22 +24,31 @@
25
24
  fit?: ImageFit;
26
25
  busy?: boolean;
27
26
  disabled?: boolean;
28
- placeholderKey?: string;
29
27
  loading?: ImageLoading;
30
28
  brushSize?: number;
31
29
  tool?: MaskTool;
32
30
  clearRevision?: number;
33
31
  exportSize?: number;
34
- class?: string;
32
+ aspectRatio?: string;
35
33
  } = $props();
36
34
 
37
35
  const canEdit = $derived(Boolean(src) && !busy && !disabled);
38
36
  </script>
39
37
 
40
- <div class={`image-mask relative ${className}`}>
41
- <Image {src} {alt} {fit} {busy} {placeholderKey} {loading} class="size-full">
38
+ <div
39
+ class="image-mask relative"
40
+ style={aspectRatio ? `aspect-ratio: ${aspectRatio}; height: auto;` : ''}
41
+ >
42
+ <Image {src} {alt} {fit} {busy} {loading}>
42
43
  {#if canEdit}
43
44
  <MaskLayer bind:mask {tool} {brushSize} {exportSize} {disabled} {clearRevision} />
44
45
  {/if}
45
46
  </Image>
46
47
  </div>
48
+
49
+ <style>
50
+ .image-mask {
51
+ width: 100%;
52
+ height: 100%;
53
+ }
54
+ </style>
@@ -7,13 +7,12 @@ type $$ComponentProps = {
7
7
  fit?: ImageFit;
8
8
  busy?: boolean;
9
9
  disabled?: boolean;
10
- placeholderKey?: string;
11
10
  loading?: ImageLoading;
12
11
  brushSize?: number;
13
12
  tool?: MaskTool;
14
13
  clearRevision?: number;
15
14
  exportSize?: number;
16
- class?: string;
15
+ aspectRatio?: string;
17
16
  };
18
17
  declare const ImageMask: import("svelte").Component<$$ComponentProps, {}, "mask" | "brushSize" | "tool" | "clearRevision">;
19
18
  type ImageMask = ReturnType<typeof ImageMask>;