svseeds 0.4.0 → 0.4.3

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 (51) hide show
  1. package/_svseeds/Accordion.svelte +31 -14
  2. package/_svseeds/Accordion.svelte.d.ts +20 -4
  3. package/_svseeds/DarkToggle.svelte +81 -41
  4. package/_svseeds/DarkToggle.svelte.d.ts +23 -4
  5. package/_svseeds/TagsInput.svelte +58 -28
  6. package/_svseeds/TagsInput.svelte.d.ts +34 -6
  7. package/_svseeds/TagsInputField.svelte +66 -33
  8. package/_svseeds/TagsInputField.svelte.d.ts +36 -4
  9. package/_svseeds/ToggleGroupField.svelte +59 -32
  10. package/_svseeds/ToggleGroupField.svelte.d.ts +30 -4
  11. package/_svseeds/_Badge.svelte +33 -17
  12. package/_svseeds/_Badge.svelte.d.ts +17 -2
  13. package/_svseeds/_Button.svelte +39 -20
  14. package/_svseeds/_Button.svelte.d.ts +20 -2
  15. package/_svseeds/_CheckField.svelte +54 -30
  16. package/_svseeds/_CheckField.svelte.d.ts +24 -2
  17. package/_svseeds/_ColorPicker.svelte +38 -17
  18. package/_svseeds/_ColorPicker.svelte.d.ts +21 -2
  19. package/_svseeds/_ComboBox.svelte +38 -20
  20. package/_svseeds/_ComboBox.svelte.d.ts +17 -2
  21. package/_svseeds/_ContextMenu.svelte +26 -12
  22. package/_svseeds/_ContextMenu.svelte.d.ts +15 -2
  23. package/_svseeds/_Disclosure.svelte +37 -21
  24. package/_svseeds/_Disclosure.svelte.d.ts +19 -3
  25. package/_svseeds/_HotkeyCapture.svelte +28 -13
  26. package/_svseeds/_HotkeyCapture.svelte.d.ts +16 -2
  27. package/_svseeds/_Modal.svelte +32 -15
  28. package/_svseeds/_Modal.svelte.d.ts +18 -3
  29. package/_svseeds/_ProgressTracker.svelte +31 -16
  30. package/_svseeds/_ProgressTracker.svelte.d.ts +16 -2
  31. package/_svseeds/_SelectField.svelte +53 -29
  32. package/_svseeds/_SelectField.svelte.d.ts +25 -2
  33. package/_svseeds/_Slider.svelte +43 -22
  34. package/_svseeds/_Slider.svelte.d.ts +22 -2
  35. package/_svseeds/_Sortable.svelte +57 -19
  36. package/_svseeds/_Sortable.svelte.d.ts +39 -2
  37. package/_svseeds/_Tabs.svelte +31 -17
  38. package/_svseeds/_Tabs.svelte.d.ts +16 -3
  39. package/_svseeds/_TextField.svelte +56 -31
  40. package/_svseeds/_TextField.svelte.d.ts +26 -2
  41. package/_svseeds/_Toggle.svelte +45 -25
  42. package/_svseeds/_Toggle.svelte.d.ts +21 -2
  43. package/_svseeds/_ToggleGroup.svelte +32 -15
  44. package/_svseeds/_ToggleGroup.svelte.d.ts +18 -2
  45. package/_svseeds/_Tooltip.svelte +32 -13
  46. package/_svseeds/_Tooltip.svelte.d.ts +20 -2
  47. package/_svseeds/core.d.ts +186 -8
  48. package/_svseeds/core.js +1 -1
  49. package/index.d.ts +24 -24
  50. package/index.js +3 -3
  51. package/package.json +1 -1
@@ -1,15 +1,32 @@
1
+ <!--
2
+ @component
3
+ default value: `<value>`
4
+ ```ts
5
+ interface AccordionProps {
6
+ labels?: string[];
7
+ current?: number; // bindable <-1>
8
+ status?: string; // bindable <STATE.NEUTRAL>
9
+ style?: SVSStyle;
10
+ deps?: AccordionDeps;
11
+ [key: string]: unknown | Snippet;
12
+ }
13
+ interface AccordionDeps {
14
+ svsDisclosure?: Omit<DisclosureProps, DisclosureReqdProps | DisclosureBindProps>;
15
+ }
16
+ ```
17
+ -->
1
18
  <script module lang="ts">
2
- export type AccordionProps = {
3
- labels?: string[],
4
- current?: number, // bindable <-1>
5
- status?: string, // bindable <STATE.DEFAULT>
6
- style?: SVSStyle,
7
- deps?: AccordionDeps,
8
- [key: string]: unknown | Snippet,
9
- };
10
- export type AccordionDeps = {
11
- svsDisclosure?: Omit<DisclosureProps, DisclosureReqdProps | DisclosureBindProps>,
12
- };
19
+ export interface AccordionProps {
20
+ labels?: string[];
21
+ current?: number; // bindable <-1>
22
+ status?: string; // bindable <STATE.NEUTRAL>
23
+ style?: SVSStyle;
24
+ deps?: AccordionDeps;
25
+ [key: string]: unknown | Snippet;
26
+ }
27
+ export interface AccordionDeps {
28
+ svsDisclosure?: Omit<DisclosureProps, DisclosureReqdProps | DisclosureBindProps>;
29
+ }
13
30
  export type AccordionReqdProps = never;
14
31
  export type AccordionBindProps = "current" | "status";
15
32
 
@@ -28,7 +45,7 @@
28
45
  }
29
46
 
30
47
  import { type Snippet, untrack } from "svelte";
31
- import { type SVSStyle, STATE, AREA, elemId, fnClass, omit } from "./core";
48
+ import { type SVSStyle, STATE, PARTS, elemId, fnClass, omit } from "./core";
32
49
  import Disclosure, { type DisclosureProps, type DisclosureReqdProps, type DisclosureBindProps } from "./_Disclosure.svelte";
33
50
  </script>
34
51
 
@@ -36,7 +53,7 @@
36
53
  let { labels = [], current = $bindable(-1), status = $bindable(""), style, deps, ...rest }: AccordionProps = $props();
37
54
 
38
55
  // *** Initialize *** //
39
- if (!status) status = STATE.DEFAULT;
56
+ if (!status) status = STATE.NEUTRAL;
40
57
  const cls = fnClass(preset, style);
41
58
  const isStrLabel = labels.length > 0;
42
59
  const lbls = toNamedId(isStrLabel ? labels : getSnippetNames(roleLabel, rest));
@@ -84,7 +101,7 @@
84
101
  <!---------------------------------------->
85
102
 
86
103
  {#if isValidAccordion}
87
- <div class={cls(AREA.WHOLE, status)} role="group">
104
+ <div class={cls(PARTS.WHOLE, status)} role="group">
88
105
  {#each lbls as { id, name }, i (id)}
89
106
  {@const ontoggle = exclusiveToggle(i)}
90
107
  <Disclosure bind:open={opens[i]} bind:element={elems[i]} label={isStrLabel ? name : (rest[name] as Snippet)} attributes={{...deps?.svsDisclosure?.attributes, ontoggle}} {...svsDisclosure}>
@@ -1,19 +1,35 @@
1
- export type AccordionProps = {
1
+ export interface AccordionProps {
2
2
  labels?: string[];
3
3
  current?: number;
4
4
  status?: string;
5
5
  style?: SVSStyle;
6
6
  deps?: AccordionDeps;
7
7
  [key: string]: unknown | Snippet;
8
- };
9
- export type AccordionDeps = {
8
+ }
9
+ export interface AccordionDeps {
10
10
  svsDisclosure?: Omit<DisclosureProps, DisclosureReqdProps | DisclosureBindProps>;
11
- };
11
+ }
12
12
  export type AccordionReqdProps = never;
13
13
  export type AccordionBindProps = "current" | "status";
14
14
  import { type Snippet } from "svelte";
15
15
  import { type SVSStyle } from "./core";
16
16
  import { type DisclosureProps, type DisclosureReqdProps, type DisclosureBindProps } from "./_Disclosure.svelte";
17
+ /**
18
+ * default value: `<value>`
19
+ * ```ts
20
+ * interface AccordionProps {
21
+ * labels?: string[];
22
+ * current?: number; // bindable <-1>
23
+ * status?: string; // bindable <STATE.NEUTRAL>
24
+ * style?: SVSStyle;
25
+ * deps?: AccordionDeps;
26
+ * [key: string]: unknown | Snippet;
27
+ * }
28
+ * interface AccordionDeps {
29
+ * svsDisclosure?: Omit<DisclosureProps, DisclosureReqdProps | DisclosureBindProps>;
30
+ * }
31
+ * ```
32
+ */
17
33
  declare const Accordion: import("svelte").Component<AccordionProps, {}, "status" | "current">;
18
34
  type Accordion = ReturnType<typeof Accordion>;
19
35
  export default Accordion;
@@ -1,53 +1,81 @@
1
+ <!--
2
+ @component
3
+ default value: `<value>`
4
+ ```ts
5
+ interface DarkToggleProps {
6
+ dark?: boolean; // bindable <(prefers-color-scheme)>
7
+ status?: string; // bindable <STATE.NEUTRAL>
8
+ element?: HTMLButtonElement; // bindable
9
+ deps?: DarkToggleDeps;
10
+ }
11
+ export interface DarkToggleDeps {
12
+ svsToggle?: Omit<ToggleProps, ToggleReqdProps | ToggleBindProps>;
13
+ }
14
+ ```
15
+ -->
1
16
  <script module lang="ts">
2
- export type DarkToggleProps = {
3
- dark?: boolean, // bindable <true>
4
- status?: string, // bindable <STATE.DEFAULT>
5
- element?: HTMLButtonElement, // bindable
6
- deps?: DarkToggleDeps,
7
- };
8
- export type DarkToggleDeps = {
9
- svsToggle?: Omit<ToggleProps, ToggleReqdProps | ToggleBindProps>,
10
- };
17
+ export interface DarkToggleProps {
18
+ dark?: boolean; // bindable <(prefers-color-scheme)>
19
+ status?: string; // bindable <STATE.NEUTRAL>
20
+ element?: HTMLButtonElement; // bindable
21
+ deps?: DarkToggleDeps;
22
+ }
23
+ export interface DarkToggleDeps {
24
+ svsToggle?: Omit<ToggleProps, ToggleReqdProps | ToggleBindProps>;
25
+ }
11
26
  export type DarkToggleReqdProps = never;
12
27
  export type DarkToggleBindProps = "dark" | "status" | "element";
13
28
 
14
- const label = "Toggle theme color";
29
+ export const THEME = { LIGHT: "light", DARK: "dark" } as const;
30
+ export function setThemeToRoot(theme?: string) {
31
+ if (typeof window === "undefined") return;
32
+ if (!theme) theme = Theme.getPreferTheme();
33
+ window.document.documentElement.classList.add(theme);
34
+ }
35
+
36
+ const ariaLabel = "Toggle theme color";
15
37
  const preset = "svs-dark-toggle";
16
38
 
17
39
  class Theme {
18
- static #DARK = "dark";
19
- static #LIGHT = "light";
40
+ static #MEDIA_PREFER_DARK = "(prefers-color-scheme: dark)";
20
41
  static #REGEX = /\(prefers-color-scheme:\s*(light|dark)\s*\)/i;
21
42
  static #SELECTOR = ":root";
22
43
  #props: Map<string, Record<string, string>> = new Map();
23
- #dark;
44
+ #theme;
24
45
  set dark(bool: boolean) {
25
46
  this.#switch(bool);
26
47
  }
27
48
  get dark(): boolean {
28
- return this.#dark;
49
+ return this.#theme === THEME.DARK;
29
50
  }
30
51
 
31
52
  constructor() {
32
- this.#dark = Theme.#isPreferDark();
53
+ this.#theme = Theme.getPreferTheme();
33
54
  this.#initProps();
34
55
  this.#setColorScheme();
56
+ setThemeToRoot(this.#theme);
35
57
  }
36
58
  #switch(dark: boolean) {
37
- const theme = dark ? Theme.#DARK : Theme.#LIGHT;
59
+ const theme = Theme.#getThemeString(dark);
60
+ if (this.#theme === theme) return;
38
61
  if (!this.#props.has(theme)) return;
39
- this.#dark = dark;
40
- this.#apply(theme);
62
+ this.#apply(theme, this.#theme);
63
+ this.#theme = theme;
41
64
  }
42
- #apply(theme: string) {
65
+ #apply(to: string, from: string) {
43
66
  if (typeof window === "undefined") return;
44
- const style = window.document.documentElement.style;
45
- Object.entries(this.#props.get(theme) ?? {})
46
- .forEach(([name, value]) => style.setProperty(name, value));
67
+ const html = window.document.documentElement;
68
+ Object.entries(this.#props.get(to) ?? {})
69
+ .forEach(([name, value]) => html.style.setProperty(name, value));
70
+ if (html.classList.contains(from)) {
71
+ html.classList.replace(from, to);
72
+ } else {
73
+ html.classList.add(to);
74
+ }
47
75
  }
48
76
  #setColorScheme() {
49
77
  if (typeof window === "undefined") return;
50
- const themes = Object.keys(this.#props).filter((x) => x === Theme.#LIGHT || x === Theme.#DARK);
78
+ const themes = Object.keys(this.#props).filter((x) => x === THEME.LIGHT || x === THEME.DARK);
51
79
  window.document.documentElement.style.colorScheme = themes.join(" ");
52
80
  }
53
81
  #initProps() {
@@ -98,7 +126,13 @@
98
126
  }
99
127
  static #isPreferDark(): boolean {
100
128
  if (typeof window === "undefined") return true;
101
- return window.matchMedia("(prefers-color-scheme: dark)").matches;
129
+ return window.matchMedia(Theme.#MEDIA_PREFER_DARK).matches;
130
+ }
131
+ static #getThemeString(dark: boolean): string {
132
+ return dark ? THEME.DARK : THEME.LIGHT;
133
+ }
134
+ static getPreferTheme(): string {
135
+ return Theme.#getThemeString(Theme.#isPreferDark());
102
136
  }
103
137
  }
104
138
  const theme = new Theme();
@@ -108,25 +142,42 @@
108
142
  </script>
109
143
 
110
144
  <script lang="ts">
111
- let { dark = $bindable(false), status = $bindable(""), element = $bindable(), deps }: DarkToggleProps = $props();
145
+ let { dark = $bindable(), status = $bindable(""), element = $bindable(), deps }: DarkToggleProps = $props();
112
146
 
113
147
  // *** Initialize *** //
114
- if (!status) status = STATE.DEFAULT;
115
- dark = theme.dark;
148
+ if (!status) status = STATE.NEUTRAL;
149
+ if (dark === undefined) dark = theme.dark;
150
+ theme.dark = dark;
116
151
 
117
152
  // *** Initialize Deps *** //
118
153
  const svsToggle = {
119
- ...omit(deps?.svsToggle, "main", "style"),
154
+ ...omit(deps?.svsToggle, "main", "style", "attributes"),
120
155
  style: deps?.svsToggle?.style ?? `${preset} svs-toggle`,
156
+ ariaLabel,
157
+ attributes: {
158
+ ...deps?.svsToggle?.attributes,
159
+ },
121
160
  };
122
161
 
123
162
  // *** Bind Handlers *** //
124
- $effect.pre(() => { theme.dark = dark });
163
+ $effect.pre(() => { theme.dark = dark!; });
125
164
  </script>
126
165
 
127
166
  <!---------------------------------------->
128
167
 
129
- <Toggle bind:value={dark} bind:status bind:element {label} {main} {...svsToggle} />
168
+ <Toggle bind:value={dark} bind:status bind:element {...svsToggle}>
169
+ {#snippet main(status: string, value: boolean, element: HTMLButtonElement | undefined)}
170
+ {#if deps?.svsToggle?.main}
171
+ {@render deps.svsToggle.main(status, value, element)}
172
+ {:else}
173
+ {#if value}
174
+ {@render svgDark()}
175
+ {:else}
176
+ {@render svgLight()}
177
+ {/if}
178
+ {/if}
179
+ {/snippet}
180
+ </Toggle>
130
181
 
131
182
  {#snippet svgDark()}
132
183
  <svg style="width: 100%; height: 100%;" viewBox="0 0 24 24" aria-hidden="true">
@@ -139,14 +190,3 @@
139
190
  <path fill-rule="evenodd" clip-rule="evenodd" d="M11 0H13V4.06189C12.6724 4.02104 12.3387 4 12 4C11.6613 4 11.3276 4.02104 11 4.06189V0ZM7.0943 5.68018L4.22173 2.80761L2.80752 4.22183L5.6801 7.09441C6.09071 6.56618 6.56608 6.0908 7.0943 5.68018ZM4.06189 11H0V13H4.06189C4.02104 12.6724 4 12.3387 4 12C4 11.6613 4.02104 11.3276 4.06189 11ZM5.6801 16.9056L2.80751 19.7782L4.22173 21.1924L7.0943 18.3198C6.56608 17.9092 6.09071 17.4338 5.6801 16.9056ZM11 19.9381V24H13V19.9381C12.6724 19.979 12.3387 20 12 20C11.6613 20 11.3276 19.979 11 19.9381ZM16.9056 18.3199L19.7781 21.1924L21.1923 19.7782L18.3198 16.9057C17.9092 17.4339 17.4338 17.9093 16.9056 18.3199ZM19.9381 13H24V11H19.9381C19.979 11.3276 20 11.6613 20 12C20 12.3387 19.979 12.6724 19.9381 13ZM18.3198 7.0943L21.1923 4.22183L19.7781 2.80762L16.9056 5.6801C17.4338 6.09071 17.9092 6.56608 18.3198 7.0943Z" />
140
191
  </svg>
141
192
  {/snippet}
142
- {#snippet main(status: string, value: boolean, element: HTMLButtonElement | undefined)}
143
- {#if deps?.svsToggle?.main}
144
- {@render deps.svsToggle.main(status, value, element)}
145
- {:else}
146
- {#if value}
147
- {@render svgDark()}
148
- {:else}
149
- {@render svgLight()}
150
- {/if}
151
- {/if}
152
- {/snippet}
@@ -1,15 +1,34 @@
1
- export type DarkToggleProps = {
1
+ export interface DarkToggleProps {
2
2
  dark?: boolean;
3
3
  status?: string;
4
4
  element?: HTMLButtonElement;
5
5
  deps?: DarkToggleDeps;
6
- };
7
- export type DarkToggleDeps = {
6
+ }
7
+ export interface DarkToggleDeps {
8
8
  svsToggle?: Omit<ToggleProps, ToggleReqdProps | ToggleBindProps>;
9
- };
9
+ }
10
10
  export type DarkToggleReqdProps = never;
11
11
  export type DarkToggleBindProps = "dark" | "status" | "element";
12
+ export declare const THEME: {
13
+ readonly LIGHT: "light";
14
+ readonly DARK: "dark";
15
+ };
16
+ export declare function setThemeToRoot(theme?: string): void;
12
17
  import { type ToggleProps, type ToggleReqdProps, type ToggleBindProps } from "./_Toggle.svelte";
18
+ /**
19
+ * default value: `<value>`
20
+ * ```ts
21
+ * interface DarkToggleProps {
22
+ * dark?: boolean; // bindable <(prefers-color-scheme)>
23
+ * status?: string; // bindable <STATE.NEUTRAL>
24
+ * element?: HTMLButtonElement; // bindable
25
+ * deps?: DarkToggleDeps;
26
+ * }
27
+ * export interface DarkToggleDeps {
28
+ * svsToggle?: Omit<ToggleProps, ToggleReqdProps | ToggleBindProps>;
29
+ * }
30
+ * ```
31
+ */
13
32
  declare const DarkToggle: import("svelte").Component<DarkToggleProps, {}, "status" | "element" | "dark">;
14
33
  type DarkToggle = ReturnType<typeof DarkToggle>;
15
34
  export default DarkToggle;
@@ -1,29 +1,58 @@
1
+ <!--
2
+ @component
3
+ default value: `<value>`
4
+ ```ts
5
+ interface TagsInputProps {
6
+ values?: string[]; // bindable
7
+ value?: string; // bindable
8
+ type?: "left" | "right"; // <"left">
9
+ confirm?: string[]; // <["Enter"]>
10
+ trim?: boolean; // <true>
11
+ unique?: boolean; // <true>
12
+ ariaErrMsgId?: string; // bindable
13
+ events?: TagsInputEvents;
14
+ status?: string; // bindable <STATE.NEUTRAL>
15
+ style?: SVSStyle;
16
+ attributes?: HTMLInputAttributes;
17
+ action?: Action;
18
+ element?: HTMLInputElement; // bindable
19
+ deps?: TagsInputDeps;
20
+ }
21
+ interface TagsInputDeps {
22
+ svsBadge?: Omit<BadgeProps, BadgeReqdProps | BadgeBindProps | "type" | "href">;
23
+ }
24
+ interface TagsInputEvents { // cancel if true
25
+ onadd?: (values: string[], value: string) => void | boolean;
26
+ onremove?: (values: string[], value: string, index: number) => void | boolean;
27
+ }
28
+ ```
29
+ -->
1
30
  <script module lang="ts">
2
- export type TagsInputProps = {
3
- values?: string[], // bindable
4
- value?: string, // bindable
5
- type?: "left" | "right", // <"left">
6
- confirm?: string[], // <["Enter"]>
7
- trim?: boolean, // <true>
8
- unique?: boolean, // <true>
9
- ariaErrMsgId?: string, // bindable
10
- events?: TagsInputEvents,
11
- status?: string, // bindable <STATE.DEFAULT>
12
- style?: SVSStyle,
13
- attributes?: HTMLInputAttributes,
14
- action?: Action,
15
- element?: HTMLInputElement, // bindable
16
- deps?: TagsInputDeps,
17
- };
18
- export type TagsInputDeps = {
19
- svsBadge?: Omit<BadgeProps, BadgeReqdProps | BadgeBindProps | "type" | "href">,
20
- };
31
+ export interface TagsInputProps {
32
+ values?: string[]; // bindable
33
+ value?: string; // bindable
34
+ type?: "left" | "right"; // <"left">
35
+ confirm?: string[]; // <["Enter"]>
36
+ trim?: boolean; // <true>
37
+ unique?: boolean; // <true>
38
+ ariaErrMsgId?: string; // bindable
39
+ events?: TagsInputEvents;
40
+ status?: string; // bindable <STATE.NEUTRAL>
41
+ style?: SVSStyle;
42
+ attributes?: HTMLInputAttributes;
43
+ action?: Action;
44
+ element?: HTMLInputElement; // bindable
45
+ deps?: TagsInputDeps;
46
+ }
47
+ export interface TagsInputDeps {
48
+ svsBadge?: Omit<BadgeProps, BadgeReqdProps | BadgeBindProps | "type" | "href">;
49
+ }
21
50
  export type TagsInputReqdProps = never;
22
51
  export type TagsInputBindProps = "values" | "value" | "ariaErrMsgId" | "status" | "element";
23
- export type TagsInputEvents = { // cancel if true
24
- onadd?: (values: string[], value: string) => void | boolean,
25
- onremove?: (values: string[], value: string, index: number) => void | boolean,
26
- };
52
+ export interface TagsInputEvents { // cancel if true
53
+ onadd?: (values: string[], value: string) => void | boolean;
54
+ onremove?: (values: string[], value: string, index: number) => void | boolean;
55
+ }
27
56
 
28
57
  type TagsInputTarget = { currentTarget: EventTarget & HTMLInputElement };
29
58
  type BadgeTarget = { currentTarget: EventTarget & HTMLButtonElement; };
@@ -32,7 +61,7 @@
32
61
 
33
62
  import { type Action } from "svelte/action";
34
63
  import { type HTMLInputAttributes } from "svelte/elements";
35
- import { type SVSStyle, STATE, AREA, fnClass, omit } from "./core";
64
+ import { type SVSStyle, STATE, PARTS, fnClass, omit } from "./core";
36
65
  import Badge, { type BadgeProps, type BadgeReqdProps, type BadgeBindProps } from "./_Badge.svelte";
37
66
  </script>
38
67
 
@@ -40,10 +69,11 @@
40
69
  let { values = $bindable([]), value = $bindable(""), type = "left", confirm = [], trim = true, unique = true, ariaErrMsgId = $bindable(), events, status = $bindable(""), style, attributes, action, element = $bindable(), deps }: TagsInputProps = $props();
41
70
 
42
71
  // *** Initialize *** //
43
- if (!status) status = STATE.DEFAULT;
72
+ if (!status) status = STATE.NEUTRAL;
44
73
  const cls = fnClass(preset, style);
45
74
  const attrs = omit(attributes, "class", "type", "onkeydown");
46
75
  const confirmKeys = new Set([CONFIRM_KEY, ...confirm]);
76
+ let invalid = $derived(ariaErrMsgId ? true : undefined);
47
77
 
48
78
  // *** Initialize Deps *** //
49
79
  const svsBadge = {
@@ -77,12 +107,12 @@
77
107
 
78
108
  <!---------------------------------------->
79
109
 
80
- <div class={cls(AREA.WHOLE, status)}>
110
+ <div class={cls(PARTS.WHOLE, status)}>
81
111
  {@render tags(type === "left")}
82
112
  {#if action}
83
- <input bind:value bind:this={element} class={cls(AREA.MAIN, status)} type="text" {onkeydown} {...attrs} use:action />
113
+ <input bind:value bind:this={element} class={cls(PARTS.MAIN, status)} type="text" {onkeydown} aria-invalid={invalid} aria-errormessage={ariaErrMsgId} {...attrs} use:action />
84
114
  {:else}
85
- <input bind:value bind:this={element} class={cls(AREA.MAIN, status)} type="text" {onkeydown} {...attrs} />
115
+ <input bind:value bind:this={element} class={cls(PARTS.MAIN, status)} type="text" {onkeydown} aria-invalid={invalid} aria-errormessage={ariaErrMsgId} {...attrs} />
86
116
  {/if}
87
117
  {@render tags(type === "right")}
88
118
  </div>
@@ -1,4 +1,4 @@
1
- export type TagsInputProps = {
1
+ export interface TagsInputProps {
2
2
  values?: string[];
3
3
  value?: string;
4
4
  type?: "left" | "right";
@@ -13,20 +13,48 @@ export type TagsInputProps = {
13
13
  action?: Action;
14
14
  element?: HTMLInputElement;
15
15
  deps?: TagsInputDeps;
16
- };
17
- export type TagsInputDeps = {
16
+ }
17
+ export interface TagsInputDeps {
18
18
  svsBadge?: Omit<BadgeProps, BadgeReqdProps | BadgeBindProps | "type" | "href">;
19
- };
19
+ }
20
20
  export type TagsInputReqdProps = never;
21
21
  export type TagsInputBindProps = "values" | "value" | "ariaErrMsgId" | "status" | "element";
22
- export type TagsInputEvents = {
22
+ export interface TagsInputEvents {
23
23
  onadd?: (values: string[], value: string) => void | boolean;
24
24
  onremove?: (values: string[], value: string, index: number) => void | boolean;
25
- };
25
+ }
26
26
  import { type Action } from "svelte/action";
27
27
  import { type HTMLInputAttributes } from "svelte/elements";
28
28
  import { type SVSStyle } from "./core";
29
29
  import { type BadgeProps, type BadgeReqdProps, type BadgeBindProps } from "./_Badge.svelte";
30
+ /**
31
+ * default value: `<value>`
32
+ * ```ts
33
+ * interface TagsInputProps {
34
+ * values?: string[]; // bindable
35
+ * value?: string; // bindable
36
+ * type?: "left" | "right"; // <"left">
37
+ * confirm?: string[]; // <["Enter"]>
38
+ * trim?: boolean; // <true>
39
+ * unique?: boolean; // <true>
40
+ * ariaErrMsgId?: string; // bindable
41
+ * events?: TagsInputEvents;
42
+ * status?: string; // bindable <STATE.NEUTRAL>
43
+ * style?: SVSStyle;
44
+ * attributes?: HTMLInputAttributes;
45
+ * action?: Action;
46
+ * element?: HTMLInputElement; // bindable
47
+ * deps?: TagsInputDeps;
48
+ * }
49
+ * interface TagsInputDeps {
50
+ * svsBadge?: Omit<BadgeProps, BadgeReqdProps | BadgeBindProps | "type" | "href">;
51
+ * }
52
+ * interface TagsInputEvents { // cancel if true
53
+ * onadd?: (values: string[], value: string) => void | boolean;
54
+ * onremove?: (values: string[], value: string, index: number) => void | boolean;
55
+ * }
56
+ * ```
57
+ */
30
58
  declare const TagsInput: import("svelte").Component<TagsInputProps, {}, "value" | "status" | "element" | "values" | "ariaErrMsgId">;
31
59
  type TagsInput = ReturnType<typeof TagsInput>;
32
60
  export default TagsInput;
@@ -1,25 +1,58 @@
1
- <script module lang="ts">
2
- export type TagsInputFieldProps = {
3
- label?: string,
4
- extra?: string,
5
- aux?: Snippet<[string, string[], HTMLInputElement | undefined]>, // Snippet<[status,values,element]>
6
- left?: Snippet<[string, string[], HTMLInputElement | undefined]>, // Snippet<[status,values,element]>
7
- right?: Snippet<[string, string[], HTMLInputElement | undefined]>, // Snippet<[status,values,element]>
8
- bottom?: string,
9
- descFirst?: boolean, // <false>
10
- values?: string[], // bindable
11
- min?: TagsInputFieldCountValidation,
12
- max?: TagsInputFieldCountValidation,
13
- constraints?: TagsInputFieldConstraint[],
14
- validations?: TagsInputFieldValidation[],
15
- status?: string, // bindable <STATE.DEFAULT>
16
- style?: SVSStyle,
17
- element?: HTMLInputElement, // bindable
18
- deps?: TagsInputFieldDeps,
1
+ <!--
2
+ @component
3
+ default value: `<value>`
4
+ ```ts
5
+ interface TagsInputFieldProps {
6
+ label?: string;
7
+ extra?: string;
8
+ aux?: Snippet<[string, string[], HTMLInputElement | undefined]>; // Snippet<[status,values,element]>
9
+ left?: Snippet<[string, string[], HTMLInputElement | undefined]>; // Snippet<[status,values,element]>
10
+ right?: Snippet<[string, string[], HTMLInputElement | undefined]>; // Snippet<[status,values,element]>
11
+ bottom?: string;
12
+ descFirst?: boolean; // <false>
13
+ values?: string[]; // bindable
14
+ min?: TagsInputFieldCountValidation;
15
+ max?: TagsInputFieldCountValidation;
16
+ constraints?: TagsInputFieldConstraint[];
17
+ validations?: TagsInputFieldValidation[];
18
+ status?: string; // bindable <STATE.NEUTRAL>
19
+ style?: SVSStyle;
20
+ element?: HTMLInputElement; // bindable
21
+ deps?: TagsInputFieldDeps;
22
+ }
23
+ interface TagsInputFieldDeps extends TagsInputDeps {
24
+ svsTagsInput?: Omit<TagsInputProps, TagsInputReqdProps | TagsInputBindProps | "deps">;
25
+ }
26
+ type TagsInputFieldConstraint = (value: string, validity: ValidityState) => string;
27
+ type TagsInputFieldValidation = (values: string[], validity: ValidityState) => string;
28
+ type TagsInputFieldCountValidation = {
29
+ value: number;
30
+ message: string;
19
31
  };
20
- export type TagsInputFieldDeps = {
21
- svsTagsInput?: Omit<TagsInputProps, TagsInputReqdProps | TagsInputBindProps | "deps">,
22
- } & TagsInputDeps;
32
+ ```
33
+ -->
34
+ <script module lang="ts">
35
+ export interface TagsInputFieldProps {
36
+ label?: string;
37
+ extra?: string;
38
+ aux?: Snippet<[string, string[], HTMLInputElement | undefined]>; // Snippet<[status,values,element]>
39
+ left?: Snippet<[string, string[], HTMLInputElement | undefined]>; // Snippet<[status,values,element]>
40
+ right?: Snippet<[string, string[], HTMLInputElement | undefined]>; // Snippet<[status,values,element]>
41
+ bottom?: string;
42
+ descFirst?: boolean; // <false>
43
+ values?: string[]; // bindable
44
+ min?: TagsInputFieldCountValidation;
45
+ max?: TagsInputFieldCountValidation;
46
+ constraints?: TagsInputFieldConstraint[];
47
+ validations?: TagsInputFieldValidation[];
48
+ status?: string; // bindable <STATE.NEUTRAL>
49
+ style?: SVSStyle;
50
+ element?: HTMLInputElement; // bindable
51
+ deps?: TagsInputFieldDeps;
52
+ }
53
+ export interface TagsInputFieldDeps extends TagsInputDeps {
54
+ svsTagsInput?: Omit<TagsInputProps, TagsInputReqdProps | TagsInputBindProps | "deps">;
55
+ }
23
56
  export type TagsInputFieldReqdProps = never;
24
57
  export type TagsInputFieldBindProps = "values" | "status" | "element";
25
58
  export type TagsInputFieldConstraint = (value: string, validity: ValidityState) => string;
@@ -29,7 +62,7 @@
29
62
  const preset = "svs-tags-input-field";
30
63
 
31
64
  import { type Snippet, untrack } from "svelte";
32
- import { type SVSStyle, STATE, AREA, elemId, fnClass, isNeutral, omit } from "./core";
65
+ import { type SVSStyle, STATE, PARTS, elemId, fnClass, isNeutral, omit } from "./core";
33
66
  import TagsInput, { type TagsInputProps, type TagsInputReqdProps, type TagsInputBindProps, type TagsInputDeps } from "./TagsInput.svelte";
34
67
  </script>
35
68
 
@@ -37,7 +70,7 @@
37
70
  let { label, extra, aux, left, right, bottom, descFirst = false, values = $bindable([]), min, max, constraints = [], validations = [], status = $bindable(""), style, element = $bindable(), deps }: TagsInputFieldProps = $props();
38
71
 
39
72
  // *** Initialize *** //
40
- if (!status) status = STATE.DEFAULT;
73
+ if (!status) status = STATE.NEUTRAL;
41
74
  const cls = fnClass(preset, style);
42
75
  const id = deps?.svsTagsInput?.attributes?.id ? deps.svsTagsInput.attributes.id : elemId.get(label?.trim());
43
76
  const idLabel = elemId.get(label?.trim());
@@ -67,7 +100,7 @@
67
100
  };
68
101
 
69
102
  // *** Status *** //
70
- let neutral = isNeutral(status) ? status : STATE.DEFAULT;
103
+ let neutral = isNeutral(status) ? status : STATE.NEUTRAL;
71
104
  $effect(() => { neutral = isNeutral(status) ? status : neutral });
72
105
  let live = $derived(status === STATE.INACTIVE ? "alert" : "status");
73
106
  let idMsg = $derived(status === STATE.INACTIVE && message?.trim() ? idErr : undefined);
@@ -128,30 +161,30 @@
128
161
 
129
162
  <!---------------------------------------->
130
163
 
131
- <div class={cls(AREA.WHOLE, status)} role="group" aria-labelledby={idLabel}>
164
+ <div class={cls(PARTS.WHOLE, status)} role="group" aria-labelledby={idLabel}>
132
165
  {#if aux}
133
- <div class={cls(AREA.TOP, status)}>
166
+ <div class={cls(PARTS.TOP, status)}>
134
167
  {@render lbl()}
135
- <span class={cls(AREA.AUX, status)}>{@render aux(status, values, element)}</span>
168
+ <span class={cls(PARTS.AUX, status)}>{@render aux(status, values, element)}</span>
136
169
  </div>
137
170
  {:else}
138
171
  {@render lbl()}
139
172
  {/if}
140
173
  {@render desc(descFirst)}
141
- <div class={cls(AREA.MIDDLE, status)}>
142
- {@render side(AREA.LEFT, left)}
174
+ <div class={cls(PARTS.MIDDLE, status)}>
175
+ {@render side(PARTS.LEFT, left)}
143
176
  <TagsInput bind:values bind:value bind:status bind:element bind:ariaErrMsgId={idMsg} {...svsTagsInput} deps={{ svsBadge }} />
144
- {@render side(AREA.RIGHT, right)}
177
+ {@render side(PARTS.RIGHT, right)}
145
178
  </div>
146
179
  {@render desc(!descFirst)}
147
180
  </div>
148
181
 
149
182
  {#snippet lbl()}
150
183
  {#if label?.trim()}
151
- <label class={cls(AREA.LABEL, status)} for={id} id={idLabel}>
184
+ <label class={cls(PARTS.LABEL, status)} for={id} id={idLabel}>
152
185
  {label}
153
186
  {#if extra?.trim()}
154
- <span class={cls(AREA.EXTRA, status)}>{extra}</span>
187
+ <span class={cls(PARTS.EXTRA, status)}>{extra}</span>
155
188
  {/if}
156
189
  </label>
157
190
  {/if}
@@ -163,7 +196,7 @@
163
196
  {/snippet}
164
197
  {#snippet desc(show: boolean)}
165
198
  {#if show && message?.trim()}
166
- <div class={cls(AREA.BOTTOM, status)} id={idDesc ?? idErr} role={live}>{message}</div>
199
+ <div class={cls(PARTS.BOTTOM, status)} id={idDesc ?? idErr} role={live}>{message}</div>
167
200
  {/if}
168
201
  {/snippet}
169
202