@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
@@ -4,15 +4,39 @@
4
4
 
5
5
  type Props = {
6
6
  text: string;
7
+ background?: string;
8
+ color?: string;
9
+ fontSize?: number;
7
10
  };
8
11
 
9
- let { text }: Props = $props();
12
+ let { text, background, color, fontSize }: Props = $props();
13
+
14
+ const toRem = (value: number | undefined) =>
15
+ value === undefined ? undefined : `${value / 10}rem`;
16
+
17
+ const overlayStyle = $derived.by(() =>
18
+ [
19
+ background ? `--sveltely-loader-background: ${background};` : '',
20
+ color ? `--sveltely-loader-color: ${color};` : '',
21
+ fontSize !== undefined ? `--sveltely-loader-font-size: ${toRem(fontSize)};` : ''
22
+ ]
23
+ .filter(Boolean)
24
+ .join(' ')
25
+ );
10
26
  </script>
11
27
 
12
- <div class="sveltely-loader-overlay" role="status" aria-live="polite" aria-label={text}>
28
+ <div
29
+ class="sveltely-loader-overlay"
30
+ role="status"
31
+ aria-live="polite"
32
+ aria-label={text || 'Loading'}
33
+ style={overlayStyle}
34
+ >
13
35
  <VStack align="center" justify="center" gap={5}>
14
- <Spinner />
15
- <span class="sveltely-loader-text">{text}</span>
36
+ <Spinner size="calc(var(--sveltely-loader-font-size) * 1.143)" />
37
+ {#if text}
38
+ <span class="sveltely-loader-text">{text}</span>
39
+ {/if}
16
40
  </VStack>
17
41
  </div>
18
42
 
@@ -25,8 +49,9 @@
25
49
  align-items: center;
26
50
  justify-content: center;
27
51
  border-radius: inherit;
28
- background: var(--sveltely-background-color, white);
29
- color: var(--sveltely-primary-color, black);
52
+ background: var(--sveltely-loader-background, var(--sveltely-background-color, white));
53
+ color: var(--sveltely-loader-color, var(--sveltely-text-primary-color, black));
54
+ font-size: var(--sveltely-loader-font-size, var(--sveltely-font-size, 1rem));
30
55
  padding: var(--sveltely-padding-y, 0.75rem) var(--sveltely-padding-x, 0.75rem);
31
56
  pointer-events: auto;
32
57
  text-align: center;
@@ -35,8 +60,8 @@
35
60
  .sveltely-loader-text {
36
61
  max-width: 100%;
37
62
  overflow: hidden;
38
- color: var(--sveltely-secondary-color, currentColor);
39
- font-size: calc(var(--sveltely-font-size, 1rem) * 0.875);
63
+ color: var(--sveltely-loader-text-color, currentColor);
64
+ font-size: var(--sveltely-loader-font-size, var(--sveltely-font-size, 1rem));
40
65
  line-height: 1.25;
41
66
  text-overflow: ellipsis;
42
67
  white-space: nowrap;
@@ -1,5 +1,8 @@
1
1
  type Props = {
2
2
  text: string;
3
+ background?: string;
4
+ color?: string;
5
+ fontSize?: number;
3
6
  };
4
7
  declare const LoaderOverlay: import("svelte").Component<Props, {}, "">;
5
8
  type LoaderOverlay = ReturnType<typeof LoaderOverlay>;
@@ -5,6 +5,9 @@ export type LoaderOptions = LoaderTrigger | [text: string, loading: LoaderTrigge
5
5
  loading?: LoaderTrigger;
6
6
  active?: LoaderTrigger;
7
7
  promise?: PromiseLike<unknown> | null;
8
+ background?: string;
9
+ color?: string;
10
+ fontSize?: number;
8
11
  disabled?: boolean;
9
12
  };
10
13
  export declare const loader: Action<HTMLElement, LoaderOptions>;
@@ -8,21 +8,30 @@ const isPromiseLike = (value) => typeof value === 'object' &&
8
8
  const parseOptions = (value = false) => {
9
9
  if (Array.isArray(value)) {
10
10
  return {
11
- text: value[0] || DEFAULT_TEXT,
11
+ text: value[0] ?? DEFAULT_TEXT,
12
12
  loading: value[1],
13
+ background: undefined,
14
+ color: undefined,
15
+ fontSize: undefined,
13
16
  disabled: false
14
17
  };
15
18
  }
16
19
  if (typeof value === 'object' && value !== null && !isPromiseLike(value)) {
17
20
  return {
18
- text: value.text || DEFAULT_TEXT,
21
+ text: value.text ?? '',
19
22
  loading: value.loading ?? value.active ?? value.promise ?? false,
23
+ background: value.background,
24
+ color: value.color,
25
+ fontSize: value.fontSize,
20
26
  disabled: value.disabled ?? false
21
27
  };
22
28
  }
23
29
  return {
24
30
  text: DEFAULT_TEXT,
25
31
  loading: value,
32
+ background: undefined,
33
+ color: undefined,
34
+ fontSize: undefined,
26
35
  disabled: false
27
36
  };
28
37
  };
@@ -37,7 +46,7 @@ export const loader = (node, initialOptions = false) => {
37
46
  const originalAriaBusy = node.getAttribute('aria-busy');
38
47
  let options = parseOptions(initialOptions);
39
48
  let overlay = null;
40
- let overlayText = '';
49
+ let overlayKey = '';
41
50
  let promiseVersion = 0;
42
51
  let appliedPosition = false;
43
52
  const ensureHostPosition = () => {
@@ -57,17 +66,21 @@ export const loader = (node, initialOptions = false) => {
57
66
  const show = () => {
58
67
  ensureHostPosition();
59
68
  node.setAttribute('aria-busy', 'true');
60
- if (overlay && overlayText === options.text) {
69
+ const nextOverlayKey = [options.text, options.background, options.color, options.fontSize].join('\0');
70
+ if (overlay && overlayKey === nextOverlayKey) {
61
71
  return;
62
72
  }
63
73
  if (overlay) {
64
74
  void unmount(overlay);
65
75
  }
66
- overlayText = options.text;
76
+ overlayKey = nextOverlayKey;
67
77
  overlay = mount(LoaderOverlay, {
68
78
  target: node,
69
79
  props: {
70
- text: options.text
80
+ text: options.text,
81
+ background: options.background,
82
+ color: options.color,
83
+ fontSize: options.fontSize
71
84
  }
72
85
  });
73
86
  };
@@ -75,7 +88,7 @@ export const loader = (node, initialOptions = false) => {
75
88
  if (overlay) {
76
89
  void unmount(overlay);
77
90
  overlay = null;
78
- overlayText = '';
91
+ overlayKey = '';
79
92
  }
80
93
  if (originalAriaBusy === null) {
81
94
  node.removeAttribute('aria-busy');
@@ -1,6 +1,6 @@
1
1
  <script module lang="ts">
2
2
  export const demo = {
3
- name: 'AnimatedNumber',
3
+ name: 'Animated Number',
4
4
  description: 'Spring-driven numeric transitions.'
5
5
  };
6
6
  </script>
@@ -17,14 +17,8 @@
17
17
  </script>
18
18
 
19
19
  <div class="vstack center gap-3">
20
- <div class="text-3xl font-semibold text-[var(--sveltely-primary-color)]">
20
+ <div class="text-3xl font-semibold text-[var(--sveltely-text-primary-color)]">
21
21
  <AnimatedNumber {value} />
22
22
  </div>
23
- <Button
24
- label="Change number"
25
- background="var(--sveltely-active-color)"
26
- borderColor="var(--sveltely-active-color)"
27
- color="var(--sveltely-background-color)"
28
- onclick={bump}
29
- />
23
+ <Button label="Change number" onclick={bump} />
30
24
  </div>
@@ -1,9 +1,9 @@
1
1
  <script lang="ts">
2
2
  import VStack from '../VStack';
3
3
  import TextEditor from '../TextEditor';
4
- import ArticleBlockFAQ from './ArticleBlockFAQ.svelte';
5
4
  import ArticleEditorBody from './ArticleEditorBody.svelte';
6
5
  import ArticleEditorHeader from './ArticleEditorHeader.svelte';
6
+ import FAQ from './Blocks/FAQ.svelte';
7
7
  import type { BlockInsertKind, BlockTextFormat } from './articleEditor.svelte.js';
8
8
  import type { ArticleEditorArticle, BlockDraft } from './types.js';
9
9
 
@@ -162,6 +162,7 @@
162
162
  <VStack gap={12.5}>
163
163
  {#each faqBlocks as block (block.id)}
164
164
  <TextEditor
165
+ as="h2"
165
166
  autosize
166
167
  value={block.text ?? 'Frequently asked questions'}
167
168
  rows={1}
@@ -169,10 +170,9 @@
169
170
  onUpdateBlock(block.id, {
170
171
  text: (event.currentTarget as HTMLTextAreaElement).value
171
172
  })}
172
- className="text-2xl leading-tight font-semibold tracking-[-0.025em] text-zinc-950 placeholder:text-zinc-300"
173
173
  placeholder="FAQ title"
174
174
  />
175
- <ArticleBlockFAQ {block} onUpdateItem={onUpdateFAQItem} />
175
+ <FAQ {block} onUpdateItem={onUpdateFAQItem} />
176
176
  {/each}
177
177
  </VStack>
178
178
  </section>
@@ -2,14 +2,13 @@
2
2
  import VStack from '../VStack';
3
3
  import type { BlockInsertKind, BlockTextFormat } from './articleEditor.svelte.js';
4
4
  import type { BlockDraft } from './types.js';
5
- import ArticleBlockCode from './ArticleBlockCode.svelte';
6
- import ArticleBlockFallback from './ArticleBlockFallback.svelte';
7
- import ArticleBlockHeading from './ArticleBlockHeading.svelte';
8
- import ArticleBlockImage from './ArticleBlockImage.svelte';
9
- import ArticleBlockList from './ArticleBlockList.svelte';
10
- import ArticleBlockParagraph from './ArticleBlockParagraph.svelte';
5
+ import Code from './Blocks/Code.svelte';
6
+ import Heading from './Blocks/Heading.svelte';
7
+ import Image from './Blocks/Image.svelte';
8
+ import List from './Blocks/List.svelte';
9
+ import Paragraph from './Blocks/Paragraph.svelte';
10
+ import Table from './Blocks/Table.svelte';
11
11
  import ArticleBlockShell from './ArticleBlockShell.svelte';
12
- import ArticleBlockTable from './ArticleBlockTable.svelte';
13
12
 
14
13
  let {
15
14
  draftTitle,
@@ -237,7 +236,7 @@
237
236
  });
238
237
  </script>
239
238
 
240
- <VStack gap={5} paddingX={0} paddingY={0}>
239
+ <VStack gap={5}>
241
240
  {#each articleBlocks as block (block.id)}
242
241
  {@const dropPlacement = dropPlacementFor(block.id)}
243
242
  {@const textFormat = blockTextFormat(block)}
@@ -257,72 +256,58 @@
257
256
  onDragStart={handleBlockDragStart}
258
257
  onDragEnd={handleBlockDragEnd}
259
258
  >
260
- {#snippet children()}
261
- {#if block.type === 'heading'}
262
- <ArticleBlockHeading
263
- {block}
264
- onUpdate={onUpdateBlock}
265
- {onCreateParagraphAfter}
266
- {onMergeBlockWithPrevious}
267
- {onRemoveBlock}
268
- shouldFocus={focusTarget === block.id}
269
- focusPosition={focusTarget === block.id ? focusPosition : null}
270
- onFocused={onFocusHandled}
271
- />
272
- {:else if block.type === 'paragraph'}
273
- <ArticleBlockParagraph
274
- {block}
275
- onUpdate={onUpdateBlock}
276
- {onCreateParagraphAfter}
277
- {onMergeBlockWithPrevious}
278
- {onRemoveBlock}
279
- {onConvertToList}
280
- shouldFocus={focusTarget === block.id}
281
- focusPosition={focusTarget === block.id ? focusPosition : null}
282
- onFocused={onFocusHandled}
283
- />
284
- {:else if block.type === 'bullet_list' || block.type === 'list' || block.type === 'numbered_list'}
285
- <ArticleBlockList
286
- {block}
287
- onUpdateItem={onUpdateListItem}
288
- onInsertItemAfter={onInsertListItemAfter}
289
- {onMergeListItemWithPrevious}
290
- {onCreateParagraphAfter}
291
- {onRemoveListItem}
292
- focusItemIndex={focusTarget?.startsWith(`${block.id}:`)
293
- ? Number(focusTarget.split(':')[1])
294
- : null}
295
- focusPosition={focusTarget?.startsWith(`${block.id}:`) ? focusPosition : null}
296
- onFocused={onFocusHandled}
297
- />
298
- {:else if block.type === 'image'}
299
- <ArticleBlockImage {block} titleFallback={draftTitle} onUpdate={onUpdateBlock} />
300
- {:else if block.type === 'table'}
301
- <ArticleBlockTable
302
- {block}
303
- onUpdateHeader={onUpdateTableHeader}
304
- onUpdateCell={onUpdateTableCell}
305
- onAddColumn={onAddTableColumn}
306
- onAddRow={onAddTableRow}
307
- onRemoveColumn={onRemoveTableColumn}
308
- onRemoveRow={onRemoveTableRow}
309
- />
310
- {:else if block.type === 'code'}
311
- <ArticleBlockCode {block} onUpdate={onUpdateBlock} />
312
- {:else}
313
- <ArticleBlockFallback
314
- {block}
315
- onUpdate={onUpdateBlock}
316
- {onCreateParagraphAfter}
317
- {onMergeBlockWithPrevious}
318
- {onRemoveBlock}
319
- {onConvertToList}
320
- shouldFocus={focusTarget === block.id}
321
- focusPosition={focusTarget === block.id ? focusPosition : null}
322
- onFocused={onFocusHandled}
323
- />
324
- {/if}
325
- {/snippet}
259
+ {#if block.type === 'heading'}
260
+ <Heading
261
+ {block}
262
+ onUpdate={onUpdateBlock}
263
+ {onCreateParagraphAfter}
264
+ {onMergeBlockWithPrevious}
265
+ {onRemoveBlock}
266
+ shouldFocus={focusTarget === block.id}
267
+ focusPosition={focusTarget === block.id ? focusPosition : null}
268
+ onFocused={onFocusHandled}
269
+ />
270
+ {:else if block.type === 'paragraph'}
271
+ <Paragraph
272
+ {block}
273
+ onUpdate={onUpdateBlock}
274
+ {onCreateParagraphAfter}
275
+ {onMergeBlockWithPrevious}
276
+ {onRemoveBlock}
277
+ {onConvertToList}
278
+ shouldFocus={focusTarget === block.id}
279
+ focusPosition={focusTarget === block.id ? focusPosition : null}
280
+ onFocused={onFocusHandled}
281
+ />
282
+ {:else if block.type === 'bullet_list' || block.type === 'list' || block.type === 'numbered_list'}
283
+ <List
284
+ {block}
285
+ onUpdateItem={onUpdateListItem}
286
+ onInsertItemAfter={onInsertListItemAfter}
287
+ {onMergeListItemWithPrevious}
288
+ {onCreateParagraphAfter}
289
+ {onRemoveListItem}
290
+ focusItemIndex={focusTarget?.startsWith(`${block.id}:`)
291
+ ? Number(focusTarget.split(':')[1])
292
+ : null}
293
+ focusPosition={focusTarget?.startsWith(`${block.id}:`) ? focusPosition : null}
294
+ onFocused={onFocusHandled}
295
+ />
296
+ {:else if block.type === 'image'}
297
+ <Image {block} titleFallback={draftTitle} onUpdate={onUpdateBlock} />
298
+ {:else if block.type === 'table'}
299
+ <Table
300
+ {block}
301
+ onUpdateHeader={onUpdateTableHeader}
302
+ onUpdateCell={onUpdateTableCell}
303
+ onAddColumn={onAddTableColumn}
304
+ onAddRow={onAddTableRow}
305
+ onRemoveColumn={onRemoveTableColumn}
306
+ onRemoveRow={onRemoveTableRow}
307
+ />
308
+ {:else if block.type === 'code'}
309
+ <Code {block} onUpdate={onUpdateBlock} />
310
+ {/if}
326
311
  </ArticleBlockShell>
327
312
  {/each}
328
313
  </VStack>
@@ -1,8 +1,8 @@
1
1
  <script lang="ts">
2
2
  import VStack from '../VStack';
3
- import ArticleImagePreview from './ArticleImagePreview.svelte';
4
3
  import TextEditor from '../TextEditor';
5
- import type { ArticleEditorArticle } from './types.js';
4
+ import Image from './Blocks/Image.svelte';
5
+ import type { ArticleEditorArticle, BlockDraft } from './types.js';
6
6
 
7
7
  let { article, draftTitle, draftImageAltText, onTitleChange, onImageAltTextChange } = $props<{
8
8
  article: ArticleEditorArticle;
@@ -11,47 +11,37 @@
11
11
  onTitleChange: (value: string) => void;
12
12
  onImageAltTextChange: (value: string) => void;
13
13
  }>();
14
+
15
+ const heroImageBlock = $derived<BlockDraft>({
16
+ id: article.id ? `${article.id}:hero-image` : 'article-hero-image',
17
+ order: -1,
18
+ type: 'image',
19
+ imageURL: article.imageURL,
20
+ imageAlt: draftImageAltText
21
+ });
22
+
23
+ const onHeroImageUpdate = (_id: string, patch: Partial<BlockDraft>) => {
24
+ if (patch.imageAlt === undefined) return;
25
+ onImageAltTextChange(patch.imageAlt ?? '');
26
+ };
14
27
  </script>
15
28
 
16
- <VStack gap={20} paddingX={0} paddingY={20}>
29
+ <VStack gap={10}>
17
30
  <TextEditor
31
+ as="h1"
18
32
  autosize
19
33
  value={draftTitle}
20
34
  rows={1}
21
35
  spellcheck={true}
22
36
  onInput={(event) => onTitleChange((event.currentTarget as HTMLTextAreaElement).value)}
23
- className="text-4xl leading-tight font-semibold tracking-[-0.03em] text-zinc-950 placeholder:text-zinc-300"
24
37
  placeholder="Untitled article"
25
38
  />
26
39
 
27
40
  {#if article.imageURL}
28
- <ArticleImagePreview
29
- src={article.imageURL}
30
- alt={draftImageAltText || article.title}
31
- aspectRatio="4 / 3"
32
- />
33
- <TextEditor
34
- autosize
35
- value={draftImageAltText}
36
- rows={1}
37
- onInput={(event) => onImageAltTextChange((event.currentTarget as HTMLTextAreaElement).value)}
38
- className="article-editor-hero-description"
39
- placeholder="Image description"
41
+ <Image
42
+ block={heroImageBlock}
43
+ titleFallback={draftTitle || article.title}
44
+ onUpdate={onHeroImageUpdate}
40
45
  />
41
46
  {/if}
42
47
  </VStack>
43
-
44
- <style>
45
- :global(.article-editor-hero-description) {
46
- border: 0;
47
- background: transparent;
48
- padding: 0;
49
- color: #3f3f46;
50
- font-size: 0.875rem;
51
- line-height: 1.5rem;
52
- }
53
-
54
- :global(.article-editor-hero-description::placeholder) {
55
- color: #d4d4d8;
56
- }
57
- </style>
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
- import TextEditor from '../TextEditor';
3
- import type { BlockDraft } from './types.js';
2
+ import TextEditor from '../../TextEditor';
3
+ import type { BlockDraft } from '../types.js';
4
4
 
5
5
  let { block, onUpdate } = $props<{
6
6
  block: BlockDraft;
@@ -16,6 +16,5 @@
16
16
  onUpdate(block.id, {
17
17
  code: (event.currentTarget as HTMLTextAreaElement).value
18
18
  })}
19
- className="bg-zinc-950 px-4 py-4 font-mono text-sm leading-6 text-zinc-100"
20
19
  placeholder="Code block"
21
20
  />
@@ -0,0 +1,8 @@
1
+ import type { BlockDraft } from '../types.js';
2
+ type $$ComponentProps = {
3
+ block: BlockDraft;
4
+ onUpdate: (id: string, patch: Partial<BlockDraft>) => void;
5
+ };
6
+ declare const Code: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type Code = ReturnType<typeof Code>;
8
+ export default Code;
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
- import TextEditor from '../TextEditor';
3
- import type { BlockDraft } from './types.js';
2
+ import TextEditor from '../../TextEditor';
3
+ import type { BlockDraft } from '../types.js';
4
4
 
5
5
  let { block, onUpdateItem } = $props<{
6
6
  block: BlockDraft;
@@ -29,9 +29,9 @@
29
29
  placeholder="Question"
30
30
  />
31
31
  <TextEditor
32
+ as="paragraph"
32
33
  autosize
33
34
  rows={1}
34
- className="text-[15px] leading-7 text-zinc-700 placeholder:text-zinc-300"
35
35
  value={item.answer}
36
36
  onInput={(event) =>
37
37
  onUpdateItem(
@@ -0,0 +1,8 @@
1
+ import type { BlockDraft } from '../types.js';
2
+ type $$ComponentProps = {
3
+ block: BlockDraft;
4
+ onUpdateItem: (blockID: string, index: number, field: 'question' | 'answer', value: string) => void;
5
+ };
6
+ declare const FAQ: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type FAQ = ReturnType<typeof FAQ>;
8
+ export default FAQ;
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
- import TextEditor from '../TextEditor';
3
- import type { BlockDraft } from './types.js';
2
+ import TextEditor from '../../TextEditor';
3
+ import type { TextAs } from '../../../../style/text';
4
+ import type { BlockDraft } from '../types.js';
4
5
 
5
6
  let {
6
7
  block,
@@ -21,9 +22,15 @@
21
22
  focusPosition?: number | null;
22
23
  onFocused?: () => void;
23
24
  }>();
25
+
26
+ const headingAs = $derived.by<TextAs>(() => {
27
+ const level = Math.min(6, Math.max(1, block.level ?? 2));
28
+ return `h${level}` as TextAs;
29
+ });
24
30
  </script>
25
31
 
26
32
  <TextEditor
33
+ as={headingAs}
27
34
  autosize
28
35
  rows={1}
29
36
  value={block.text ?? ''}
@@ -62,12 +69,5 @@
62
69
  {shouldFocus}
63
70
  {focusPosition}
64
71
  {onFocused}
65
- className={`placeholder:text-zinc-300 ${
66
- Number(block.level ?? 2) <= 1
67
- ? 'text-3xl font-semibold tracking-[-0.03em]'
68
- : Number(block.level ?? 2) === 2
69
- ? 'text-2xl font-semibold tracking-[-0.025em]'
70
- : 'text-xl font-semibold'
71
- }`}
72
72
  placeholder="Heading"
73
73
  />
@@ -1,4 +1,4 @@
1
- import type { BlockDraft } from './types.js';
1
+ import type { BlockDraft } from '../types.js';
2
2
  type $$ComponentProps = {
3
3
  block: BlockDraft;
4
4
  onUpdate: (id: string, patch: Partial<BlockDraft>) => void;
@@ -9,6 +9,6 @@ type $$ComponentProps = {
9
9
  focusPosition?: number | null;
10
10
  onFocused?: () => void;
11
11
  };
12
- declare const ArticleBlockHeading: import("svelte").Component<$$ComponentProps, {}, "">;
13
- type ArticleBlockHeading = ReturnType<typeof ArticleBlockHeading>;
14
- export default ArticleBlockHeading;
12
+ declare const Heading: import("svelte").Component<$$ComponentProps, {}, "">;
13
+ type Heading = ReturnType<typeof Heading>;
14
+ export default Heading;
@@ -0,0 +1,32 @@
1
+ <script lang="ts">
2
+ import Image from '../../Image';
3
+ import TextEditor from '../../TextEditor';
4
+ import VStack from '../../VStack';
5
+ import type { BlockDraft } from '../types.js';
6
+
7
+ let { block, titleFallback, onUpdate } = $props<{
8
+ block: BlockDraft;
9
+ titleFallback: string;
10
+ onUpdate: (id: string, patch: Partial<BlockDraft>) => void;
11
+ }>();
12
+ </script>
13
+
14
+ <VStack gap={10}>
15
+ <Image
16
+ src={block.imageURL}
17
+ alt={block.imageAlt ?? titleFallback}
18
+ fit="cover"
19
+ aspectRatio="4 / 3"
20
+ />
21
+
22
+ <TextEditor
23
+ as="paragraph"
24
+ autosize
25
+ rows={1}
26
+ value={block.imageAlt ?? ''}
27
+ onInput={(event) =>
28
+ onUpdate(block.id, {
29
+ imageAlt: (event.currentTarget as HTMLTextAreaElement).value
30
+ })}
31
+ />
32
+ </VStack>
@@ -0,0 +1,10 @@
1
+ import Image from '../../Image';
2
+ import type { BlockDraft } from '../types.js';
3
+ type $$ComponentProps = {
4
+ block: BlockDraft;
5
+ titleFallback: string;
6
+ onUpdate: (id: string, patch: Partial<BlockDraft>) => void;
7
+ };
8
+ declare const Image: import("svelte").Component<$$ComponentProps, {}, "">;
9
+ type Image = ReturnType<typeof Image>;
10
+ export default Image;
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
- import TextEditor from '../TextEditor';
3
- import type { BlockDraft } from './types.js';
2
+ import TextEditor from '../../TextEditor';
3
+ import type { BlockDraft } from '../types.js';
4
4
 
5
5
  let {
6
6
  block,
@@ -66,6 +66,7 @@
66
66
  {#each block.items ?? [] as item, index}
67
67
  <li class="article-editor-list-item pl-2">
68
68
  <TextEditor
69
+ as="paragraph"
69
70
  autosize
70
71
  rows={1}
71
72
  value={item}
@@ -75,7 +76,6 @@
75
76
  shouldFocus={focusItemIndex === index}
76
77
  focusPosition={focusItemIndex === index ? focusPosition : null}
77
78
  {onFocused}
78
- className="text-[17px] leading-7 text-zinc-700 placeholder:text-zinc-300"
79
79
  placeholder="List item"
80
80
  />
81
81
  </li>
@@ -88,6 +88,7 @@
88
88
  {#each block.items ?? [] as item, index}
89
89
  <li class="article-editor-list-item pl-2">
90
90
  <TextEditor
91
+ as="paragraph"
91
92
  autosize
92
93
  rows={1}
93
94
  value={item}
@@ -97,7 +98,6 @@
97
98
  shouldFocus={focusItemIndex === index}
98
99
  focusPosition={focusItemIndex === index ? focusPosition : null}
99
100
  {onFocused}
100
- className="text-[17px] leading-7 text-zinc-700 placeholder:text-zinc-300"
101
101
  placeholder="List item"
102
102
  />
103
103
  </li>
@@ -1,4 +1,4 @@
1
- import type { BlockDraft } from './types.js';
1
+ import type { BlockDraft } from '../types.js';
2
2
  type $$ComponentProps = {
3
3
  block: BlockDraft;
4
4
  onUpdateItem: (blockID: string, index: number, value: string) => void;
@@ -10,6 +10,6 @@ type $$ComponentProps = {
10
10
  focusPosition?: number | null;
11
11
  onFocused?: () => void;
12
12
  };
13
- declare const ArticleBlockList: import("svelte").Component<$$ComponentProps, {}, "">;
14
- type ArticleBlockList = ReturnType<typeof ArticleBlockList>;
15
- export default ArticleBlockList;
13
+ declare const List: import("svelte").Component<$$ComponentProps, {}, "">;
14
+ type List = ReturnType<typeof List>;
15
+ export default List;