@tabelhadev/tabelhawebui 0.28.4

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 (175) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +222 -0
  3. package/README.pt-BR.md +217 -0
  4. package/dist/actions/click-outside.d.ts +3 -0
  5. package/dist/actions/click-outside.js +12 -0
  6. package/dist/actions/combobox-keyboard-nav.d.ts +9 -0
  7. package/dist/actions/combobox-keyboard-nav.js +28 -0
  8. package/dist/actions/focus-trap.d.ts +1 -0
  9. package/dist/actions/focus-trap.js +34 -0
  10. package/dist/actions/scroll-lock.d.ts +1 -0
  11. package/dist/actions/scroll-lock.js +17 -0
  12. package/dist/components/actions/Button.svelte +169 -0
  13. package/dist/components/actions/Button.svelte.d.ts +19 -0
  14. package/dist/components/appshell/AppShell.svelte +50 -0
  15. package/dist/components/appshell/AppShell.svelte.d.ts +19 -0
  16. package/dist/components/appshell/AppShellBottomNav.svelte +67 -0
  17. package/dist/components/appshell/AppShellBottomNav.svelte.d.ts +9 -0
  18. package/dist/components/appshell/AppShellContent.svelte +38 -0
  19. package/dist/components/appshell/AppShellContent.svelte.d.ts +10 -0
  20. package/dist/components/appshell/AppShellSidebar.svelte +196 -0
  21. package/dist/components/appshell/AppShellSidebar.svelte.d.ts +15 -0
  22. package/dist/components/appshell/types.d.ts +6 -0
  23. package/dist/components/appshell/types.js +1 -0
  24. package/dist/components/appshell/utils.d.ts +1 -0
  25. package/dist/components/appshell/utils.js +3 -0
  26. package/dist/components/card/Card.svelte +31 -0
  27. package/dist/components/card/Card.svelte.d.ts +9 -0
  28. package/dist/components/card/CardAction.svelte +57 -0
  29. package/dist/components/card/CardAction.svelte.d.ts +10 -0
  30. package/dist/components/card/CardContent.svelte +25 -0
  31. package/dist/components/card/CardContent.svelte.d.ts +8 -0
  32. package/dist/components/card/CardDescription.svelte +24 -0
  33. package/dist/components/card/CardDescription.svelte.d.ts +8 -0
  34. package/dist/components/card/CardFooter.svelte +25 -0
  35. package/dist/components/card/CardFooter.svelte.d.ts +8 -0
  36. package/dist/components/card/CardHeader.svelte +54 -0
  37. package/dist/components/card/CardHeader.svelte.d.ts +10 -0
  38. package/dist/components/card/CardTitle.svelte +25 -0
  39. package/dist/components/card/CardTitle.svelte.d.ts +8 -0
  40. package/dist/components/chat/ChatMessage.svelte +104 -0
  41. package/dist/components/chat/ChatMessage.svelte.d.ts +10 -0
  42. package/dist/components/choice/Listbox.svelte +183 -0
  43. package/dist/components/choice/Listbox.svelte.d.ts +15 -0
  44. package/dist/components/choice/MultiSelect.svelte +278 -0
  45. package/dist/components/choice/MultiSelect.svelte.d.ts +18 -0
  46. package/dist/components/choice/Rating.svelte +91 -0
  47. package/dist/components/choice/Rating.svelte.d.ts +12 -0
  48. package/dist/components/choice/Toggle.svelte +112 -0
  49. package/dist/components/choice/Toggle.svelte.d.ts +12 -0
  50. package/dist/components/feedback/Badge.svelte +66 -0
  51. package/dist/components/feedback/Badge.svelte.d.ts +9 -0
  52. package/dist/components/feedback/ErrorPage.svelte +99 -0
  53. package/dist/components/feedback/ErrorPage.svelte.d.ts +13 -0
  54. package/dist/components/feedback/Message.svelte +130 -0
  55. package/dist/components/feedback/Message.svelte.d.ts +14 -0
  56. package/dist/components/feedback/ProgressBar.svelte +69 -0
  57. package/dist/components/feedback/ProgressBar.svelte.d.ts +8 -0
  58. package/dist/components/feedback/Skeleton.svelte +47 -0
  59. package/dist/components/feedback/Skeleton.svelte.d.ts +9 -0
  60. package/dist/components/feedback/Status.svelte +75 -0
  61. package/dist/components/feedback/Status.svelte.d.ts +10 -0
  62. package/dist/components/feedback/StatusPill.svelte +94 -0
  63. package/dist/components/feedback/StatusPill.svelte.d.ts +13 -0
  64. package/dist/components/feedback/Toaster.svelte +122 -0
  65. package/dist/components/feedback/Toaster.svelte.d.ts +7 -0
  66. package/dist/components/feedback/Tooltip.svelte +126 -0
  67. package/dist/components/feedback/Tooltip.svelte.d.ts +10 -0
  68. package/dist/components/feedback/toast.svelte.d.ts +27 -0
  69. package/dist/components/feedback/toast.svelte.js +23 -0
  70. package/dist/components/forms/Checkbox.svelte +96 -0
  71. package/dist/components/forms/Checkbox.svelte.d.ts +11 -0
  72. package/dist/components/forms/DatePicker.svelte +372 -0
  73. package/dist/components/forms/DatePicker.svelte.d.ts +21 -0
  74. package/dist/components/forms/Field.svelte +47 -0
  75. package/dist/components/forms/Field.svelte.d.ts +11 -0
  76. package/dist/components/forms/FileUpload.svelte +504 -0
  77. package/dist/components/forms/FileUpload.svelte.d.ts +43 -0
  78. package/dist/components/forms/Input.svelte +93 -0
  79. package/dist/components/forms/Input.svelte.d.ts +9 -0
  80. package/dist/components/forms/Label.svelte +30 -0
  81. package/dist/components/forms/Label.svelte.d.ts +10 -0
  82. package/dist/components/forms/Radio.svelte +80 -0
  83. package/dist/components/forms/Radio.svelte.d.ts +11 -0
  84. package/dist/components/forms/Select.svelte +322 -0
  85. package/dist/components/forms/Select.svelte.d.ts +22 -0
  86. package/dist/components/forms/TagInput.svelte +336 -0
  87. package/dist/components/forms/TagInput.svelte.d.ts +16 -0
  88. package/dist/components/forms/Textarea.svelte +64 -0
  89. package/dist/components/forms/Textarea.svelte.d.ts +9 -0
  90. package/dist/components/landing/Landing.svelte +47 -0
  91. package/dist/components/landing/Landing.svelte.d.ts +8 -0
  92. package/dist/components/landing/LandingFeatures.svelte +92 -0
  93. package/dist/components/landing/LandingFeatures.svelte.d.ts +15 -0
  94. package/dist/components/landing/LandingHero.svelte +92 -0
  95. package/dist/components/landing/LandingHero.svelte.d.ts +13 -0
  96. package/dist/components/landing/LandingRoadmap.svelte +42 -0
  97. package/dist/components/landing/LandingRoadmap.svelte.d.ts +11 -0
  98. package/dist/components/landing/LandingSection.svelte +25 -0
  99. package/dist/components/landing/LandingSection.svelte.d.ts +9 -0
  100. package/dist/components/landing/LandingSectionHeading.svelte +19 -0
  101. package/dist/components/landing/LandingSectionHeading.svelte.d.ts +10 -0
  102. package/dist/components/landing/LandingSteps.svelte +100 -0
  103. package/dist/components/landing/LandingSteps.svelte.d.ts +13 -0
  104. package/dist/components/layout/BracketLink.svelte +41 -0
  105. package/dist/components/layout/BracketLink.svelte.d.ts +9 -0
  106. package/dist/components/layout/Divider.svelte +70 -0
  107. package/dist/components/layout/Divider.svelte.d.ts +9 -0
  108. package/dist/components/layout/Eyebrow.svelte +24 -0
  109. package/dist/components/layout/Eyebrow.svelte.d.ts +8 -0
  110. package/dist/components/layout/PageHeader.svelte +106 -0
  111. package/dist/components/layout/PageHeader.svelte.d.ts +15 -0
  112. package/dist/components/layout/PageSeo.svelte +34 -0
  113. package/dist/components/layout/PageSeo.svelte.d.ts +10 -0
  114. package/dist/components/layout/PageShell.svelte +25 -0
  115. package/dist/components/layout/PageShell.svelte.d.ts +8 -0
  116. package/dist/components/layout/Panel.svelte +105 -0
  117. package/dist/components/layout/Panel.svelte.d.ts +12 -0
  118. package/dist/components/layout/Prose.svelte +101 -0
  119. package/dist/components/layout/Prose.svelte.d.ts +7 -0
  120. package/dist/components/layout/RuleCard.svelte +63 -0
  121. package/dist/components/layout/RuleCard.svelte.d.ts +13 -0
  122. package/dist/components/layout/SectionHeading.svelte +57 -0
  123. package/dist/components/layout/SectionHeading.svelte.d.ts +10 -0
  124. package/dist/components/layout/StatTile.svelte +76 -0
  125. package/dist/components/layout/StatTile.svelte.d.ts +12 -0
  126. package/dist/components/layout/TerminalWindow.svelte +81 -0
  127. package/dist/components/layout/TerminalWindow.svelte.d.ts +9 -0
  128. package/dist/components/layout/Wordmark.svelte +26 -0
  129. package/dist/components/layout/Wordmark.svelte.d.ts +8 -0
  130. package/dist/components/list/List.svelte +40 -0
  131. package/dist/components/list/List.svelte.d.ts +13 -0
  132. package/dist/components/list/ListItem.svelte +81 -0
  133. package/dist/components/list/ListItem.svelte.d.ts +13 -0
  134. package/dist/components/marketing/MarketingShell.svelte +170 -0
  135. package/dist/components/marketing/MarketingShell.svelte.d.ts +23 -0
  136. package/dist/components/marketing/MarketingShellFooter.svelte +92 -0
  137. package/dist/components/marketing/MarketingShellFooter.svelte.d.ts +14 -0
  138. package/dist/components/navigation/Accordion.svelte +110 -0
  139. package/dist/components/navigation/Accordion.svelte.d.ts +15 -0
  140. package/dist/components/navigation/Carousel.svelte +115 -0
  141. package/dist/components/navigation/Carousel.svelte.d.ts +12 -0
  142. package/dist/components/navigation/InstructionStep.svelte +115 -0
  143. package/dist/components/navigation/InstructionStep.svelte.d.ts +10 -0
  144. package/dist/components/navigation/InstructionSteps.svelte +39 -0
  145. package/dist/components/navigation/InstructionSteps.svelte.d.ts +8 -0
  146. package/dist/components/navigation/Nav.svelte +102 -0
  147. package/dist/components/navigation/Nav.svelte.d.ts +14 -0
  148. package/dist/components/navigation/Stepper.svelte +112 -0
  149. package/dist/components/navigation/Stepper.svelte.d.ts +12 -0
  150. package/dist/components/navigation/TabCard.svelte +62 -0
  151. package/dist/components/navigation/TabCard.svelte.d.ts +10 -0
  152. package/dist/components/navigation/Tabs.svelte +83 -0
  153. package/dist/components/navigation/Tabs.svelte.d.ts +12 -0
  154. package/dist/components/navigation/ThemeToggle.svelte +118 -0
  155. package/dist/components/navigation/ThemeToggle.svelte.d.ts +20 -0
  156. package/dist/components/overlay/Dialog.svelte +200 -0
  157. package/dist/components/overlay/Dialog.svelte.d.ts +19 -0
  158. package/dist/components/overlay/DialogActions.svelte +50 -0
  159. package/dist/components/overlay/DialogActions.svelte.d.ts +9 -0
  160. package/dist/components/overlay/Dropdown.svelte +110 -0
  161. package/dist/components/overlay/Dropdown.svelte.d.ts +10 -0
  162. package/dist/components/overlay/FloatingActionPill.svelte +96 -0
  163. package/dist/components/overlay/FloatingActionPill.svelte.d.ts +14 -0
  164. package/dist/components/overlay/Sidebar.svelte +258 -0
  165. package/dist/components/overlay/Sidebar.svelte.d.ts +18 -0
  166. package/dist/components/table/Table.svelte +550 -0
  167. package/dist/components/table/Table.svelte.d.ts +42 -0
  168. package/dist/components/timeline/Timeline.svelte +25 -0
  169. package/dist/components/timeline/Timeline.svelte.d.ts +8 -0
  170. package/dist/components/timeline/TimelineItem.svelte +220 -0
  171. package/dist/components/timeline/TimelineItem.svelte.d.ts +18 -0
  172. package/dist/index.d.ts +156 -0
  173. package/dist/index.js +149 -0
  174. package/dist/theme/theme.css +348 -0
  175. package/package.json +52 -0
@@ -0,0 +1,115 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import { getContext } from 'svelte';
4
+ import CardRoot from '../card/Card.svelte';
5
+ import CardHeader from '../card/CardHeader.svelte';
6
+ import CardContent from '../card/CardContent.svelte';
7
+
8
+ let {
9
+ title,
10
+ action,
11
+ n,
12
+ children
13
+ }: {
14
+ title?: string;
15
+ action?: Snippet;
16
+ n?: number;
17
+ children: Snippet;
18
+ } = $props();
19
+
20
+ const register = getContext<(() => number) | undefined>('twui-instruction-step');
21
+ const stepNumber = $derived(n ?? (register ? register() : 1));
22
+ </script>
23
+
24
+ <CardRoot class="twui-instruction-step" variant="base">
25
+ <CardHeader class="twui-instruction-step-header">
26
+ {#snippet title()}
27
+ <span class="twui-instruction-step-head">
28
+ <span class="twui-instruction-step-badge">{stepNumber}</span>
29
+ {#if title}
30
+ <span class="twui-instruction-step-title">{title}</span>
31
+ {/if}
32
+ </span>
33
+ {/snippet}
34
+ <!-- Must be a DIRECT child of <CardHeader>: a snippet declared
35
+ inside an {#if} block is scoped to that block and never
36
+ reaches the component as its `children` prop. -->
37
+ {#snippet children()}
38
+ {#if action}
39
+ {@render action()}
40
+ {/if}
41
+ {/snippet}
42
+ </CardHeader>
43
+ <CardContent>
44
+ <div class="twui-instruction-step-content">
45
+ {@render children()}
46
+ </div>
47
+ </CardContent>
48
+ </CardRoot>
49
+
50
+ <style>
51
+ .twui-instruction-step-head {
52
+ display: flex;
53
+ align-items: center;
54
+ gap: 8px;
55
+ min-width: 0;
56
+ }
57
+
58
+ .twui-instruction-step-badge {
59
+ display: flex;
60
+ align-items: center;
61
+ justify-content: center;
62
+ flex-shrink: 0;
63
+ width: 24px;
64
+ height: 24px;
65
+ border: 1px solid var(--twui-accent);
66
+ background: color-mix(in oklab, var(--twui-accent) 10%, transparent);
67
+ font-family: var(--twui-font-mono);
68
+ font-size: 12px;
69
+ font-weight: 600;
70
+ color: var(--twui-accent);
71
+ }
72
+
73
+ .twui-instruction-step-title {
74
+ margin: 0;
75
+ font-family: var(--twui-font-mono);
76
+ font-size: 14px;
77
+ font-weight: 600;
78
+ color: var(--twui-ink);
79
+ }
80
+
81
+ /* Block (not flex column) so inline <code>/<kbd>/<a> flow normally
82
+ instead of each becoming its own full-width line. */
83
+ .twui-instruction-step-content {
84
+ font-size: 15px;
85
+ color: var(--twui-ink-soft);
86
+ }
87
+
88
+ /* Only bare <code>/<kbd>/<a> (no class) get auto-styled, so callers
89
+ can still opt out with their own classes (e.g. the token display box). */
90
+ .twui-instruction-step-content :global(code:not([class])),
91
+ .twui-instruction-step-content :global(kbd:not([class])) {
92
+ border: 1px solid var(--twui-rule);
93
+ background: var(--twui-paper-raised);
94
+ padding: 1px 4px;
95
+ font-family: var(--twui-font-mono);
96
+ font-size: 12px;
97
+ border-radius: 4px;
98
+ color: var(--twui-ink);
99
+ }
100
+
101
+ .twui-instruction-step-content :global(a:not([class])) {
102
+ color: var(--twui-accent);
103
+ text-decoration: underline;
104
+ text-underline-offset: 4px;
105
+ }
106
+
107
+ .twui-instruction-step-content :global(a:not([class])):hover {
108
+ opacity: 0.8;
109
+ }
110
+
111
+ .twui-instruction-step-content :global(strong) {
112
+ color: var(--twui-ink);
113
+ font-weight: 600;
114
+ }
115
+ </style>
@@ -0,0 +1,10 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ title?: string;
4
+ action?: Snippet;
5
+ n?: number;
6
+ children: Snippet;
7
+ };
8
+ declare const InstructionStep: import("svelte").Component<$$ComponentProps, {}, "">;
9
+ type InstructionStep = ReturnType<typeof InstructionStep>;
10
+ export default InstructionStep;
@@ -0,0 +1,39 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import { setContext } from 'svelte';
4
+
5
+ let {
6
+ children,
7
+ class: className = ''
8
+ }: {
9
+ children: Snippet;
10
+ class?: string;
11
+ } = $props();
12
+
13
+ let count = 0;
14
+ // Each <Instruction.Step> calls this on mount, in document order, so the
15
+ // badges number themselves sequentially without an explicit index prop.
16
+ const register = () => {
17
+ count += 1;
18
+ return count;
19
+ };
20
+ setContext('twui-instruction-step', register);
21
+ </script>
22
+
23
+ <div class="twui-instruction-steps {className}">
24
+ {@render children()}
25
+ </div>
26
+
27
+ <style>
28
+ .twui-instruction-steps {
29
+ display: flex;
30
+ flex-direction: column;
31
+ gap: 16px;
32
+ }
33
+
34
+ /* Header-only step: without the content below, the header's bottom rule
35
+ would sit right on top of the card's own border. */
36
+ .twui-instruction-step :global(.twui-card-header:last-child) {
37
+ border-bottom: none;
38
+ }
39
+ </style>
@@ -0,0 +1,8 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ children: Snippet;
4
+ class?: string;
5
+ };
6
+ declare const InstructionSteps: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type InstructionSteps = ReturnType<typeof InstructionSteps>;
8
+ export default InstructionSteps;
@@ -0,0 +1,102 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ let {
5
+ logo,
6
+ items = [],
7
+ trailing,
8
+ class: className = ''
9
+ }: {
10
+ logo?: Snippet;
11
+ items?: { href: string; label: string; current?: boolean }[];
12
+ trailing?: Snippet;
13
+ class?: string;
14
+ } = $props();
15
+ </script>
16
+
17
+ <header class="twui-nav {className}">
18
+ <div class="twui-nav-top">
19
+ {#if logo}
20
+ <div class="twui-nav-logo">{@render logo()}</div>
21
+ {/if}
22
+ {#if trailing}
23
+ <div class="twui-nav-trailing">{@render trailing()}</div>
24
+ {/if}
25
+ </div>
26
+ {#if items.length > 0}
27
+ <nav class="twui-nav-links">
28
+ {#each items as item, i (item.href)}
29
+ {#if i > 0}
30
+ <span class="twui-nav-sep" aria-hidden="true">/</span>
31
+ {/if}
32
+ <a
33
+ href={item.href}
34
+ class="twui-nav-link {item.current ? 'twui-nav-link-current' : ''}"
35
+ aria-current={item.current ? 'page' : undefined}
36
+ >{item.label}</a
37
+ >
38
+ {/each}
39
+ </nav>
40
+ {/if}
41
+ </header>
42
+
43
+ <style>
44
+ .twui-nav {
45
+ border-bottom: 1px solid var(--twui-rule);
46
+ }
47
+
48
+ .twui-nav-top {
49
+ display: flex;
50
+ align-items: center;
51
+ justify-content: space-between;
52
+ gap: 16px;
53
+ padding: 16px 20px;
54
+ }
55
+
56
+ .twui-nav-logo {
57
+ font-family: var(--twui-font-mono);
58
+ font-size: 14px;
59
+ font-weight: 500;
60
+ white-space: nowrap;
61
+ color: var(--twui-ink);
62
+ }
63
+
64
+ .twui-nav-trailing {
65
+ display: flex;
66
+ align-items: center;
67
+ gap: 12px;
68
+ }
69
+
70
+ .twui-nav-links {
71
+ display: flex;
72
+ flex-wrap: wrap;
73
+ align-items: center;
74
+ column-gap: 4px;
75
+ row-gap: 8px;
76
+ padding: 0 20px 16px;
77
+ font-family: var(--twui-font-mono);
78
+ font-size: 14px;
79
+ }
80
+
81
+ .twui-nav-sep {
82
+ padding: 0 8px;
83
+ color: var(--twui-ink-faint);
84
+ user-select: none;
85
+ }
86
+
87
+ .twui-nav-link {
88
+ color: var(--twui-ink-soft);
89
+ transition: color 0.15s ease;
90
+ }
91
+
92
+ .twui-nav-link:hover {
93
+ color: var(--twui-accent);
94
+ }
95
+
96
+ .twui-nav-link-current {
97
+ color: var(--twui-accent);
98
+ text-decoration: underline;
99
+ text-decoration-thickness: 2px;
100
+ text-underline-offset: 4px;
101
+ }
102
+ </style>
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ logo?: Snippet;
4
+ items?: {
5
+ href: string;
6
+ label: string;
7
+ current?: boolean;
8
+ }[];
9
+ trailing?: Snippet;
10
+ class?: string;
11
+ };
12
+ declare const Nav: import("svelte").Component<$$ComponentProps, {}, "">;
13
+ type Nav = ReturnType<typeof Nav>;
14
+ export default Nav;
@@ -0,0 +1,112 @@
1
+ <script lang="ts">
2
+ let {
3
+ items,
4
+ value = $bindable(''),
5
+ class: className = ''
6
+ }: {
7
+ items: { value: string; label: string; disabled?: boolean }[];
8
+ value?: string;
9
+ class?: string;
10
+ } = $props();
11
+
12
+ const currentIndex = $derived(items.findIndex((s) => s.value === value));
13
+ </script>
14
+
15
+ <ol class="twui-stepper {className}">
16
+ {#each items as step, i (step.value)}
17
+ <li
18
+ class="twui-stepper-item {i <= currentIndex ? 'twui-stepper-item-active' : ''} {step.disabled ? 'twui-stepper-item-disabled' : ''}"
19
+ aria-current={i === currentIndex ? 'step' : undefined}
20
+ >
21
+ <button
22
+ type="button"
23
+ class="twui-stepper-btn"
24
+ disabled={step.disabled}
25
+ onclick={() => (value = step.value)}
26
+ aria-label={`Passo ${i + 1} de ${items.length}: ${step.label}`}
27
+ >
28
+ <span class="twui-stepper-num" aria-hidden="true">
29
+ {i < currentIndex ? '✓' : String(i + 1).padStart(2, '0')}
30
+ </span>
31
+ <span class="twui-stepper-label">{step.label}</span>
32
+ </button>
33
+ </li>
34
+ {/each}
35
+ </ol>
36
+
37
+ <style>
38
+ .twui-stepper {
39
+ display: flex;
40
+ flex-wrap: wrap;
41
+ gap: 0;
42
+ margin: 0;
43
+ padding: 0;
44
+ list-style: none;
45
+ }
46
+
47
+ .twui-stepper-item {
48
+ position: relative;
49
+ flex: 1;
50
+ min-width: 0;
51
+ }
52
+
53
+ .twui-stepper-item::after {
54
+ content: '';
55
+ position: absolute;
56
+ top: 13px;
57
+ right: 0;
58
+ left: calc(50% + 18px);
59
+ height: 1px;
60
+ background: var(--twui-rule);
61
+ }
62
+
63
+ .twui-stepper-item:last-child::after {
64
+ display: none;
65
+ }
66
+
67
+ .twui-stepper-item-active::after {
68
+ background: var(--twui-accent);
69
+ }
70
+
71
+ .twui-stepper-btn {
72
+ display: flex;
73
+ flex-direction: column;
74
+ align-items: center;
75
+ gap: 6px;
76
+ width: 100%;
77
+ padding: 0;
78
+ border: none;
79
+ background: transparent;
80
+ font-family: var(--twui-font-mono);
81
+ cursor: pointer;
82
+ }
83
+
84
+ .twui-stepper-num {
85
+ display: flex;
86
+ align-items: center;
87
+ justify-content: center;
88
+ width: 26px;
89
+ height: 26px;
90
+ border: 1px solid var(--twui-rule);
91
+ border-radius: 9999px;
92
+ background: var(--twui-paper-raised);
93
+ font-size: 11px;
94
+ color: var(--twui-ink-soft);
95
+ }
96
+
97
+ .twui-stepper-item-active .twui-stepper-num {
98
+ border-color: var(--twui-accent);
99
+ background: var(--twui-accent);
100
+ color: var(--twui-paper);
101
+ }
102
+
103
+ .twui-stepper-label {
104
+ font-size: 12px;
105
+ color: var(--twui-ink-soft);
106
+ }
107
+
108
+ .twui-stepper-item-disabled .twui-stepper-btn {
109
+ opacity: 0.4;
110
+ cursor: not-allowed;
111
+ }
112
+ </style>
@@ -0,0 +1,12 @@
1
+ type $$ComponentProps = {
2
+ items: {
3
+ value: string;
4
+ label: string;
5
+ disabled?: boolean;
6
+ }[];
7
+ value?: string;
8
+ class?: string;
9
+ };
10
+ declare const Stepper: import("svelte").Component<$$ComponentProps, {}, "value">;
11
+ type Stepper = ReturnType<typeof Stepper>;
12
+ export default Stepper;
@@ -0,0 +1,62 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ let {
5
+ title,
6
+ note,
7
+ children,
8
+ class: className = ''
9
+ }: {
10
+ title: string;
11
+ note?: string;
12
+ children: Snippet;
13
+ class?: string;
14
+ } = $props();
15
+ </script>
16
+
17
+ <div class="twui-tabcard {className}">
18
+ <span class="twui-tabcard-tab">{title}</span>
19
+ <div class="twui-tabcard-body">
20
+ {@render children()}
21
+ {#if note}
22
+ <span class="twui-tabcard-note">{note}</span>
23
+ {/if}
24
+ </div>
25
+ </div>
26
+
27
+ <style>
28
+ .twui-tabcard {
29
+ display: flex;
30
+ height: 100%;
31
+ width: 100%;
32
+ flex-direction: column;
33
+ }
34
+
35
+ .twui-tabcard-tab {
36
+ display: inline-flex;
37
+ width: fit-content;
38
+ border: 1px solid var(--twui-rule);
39
+ border-bottom: 0;
40
+ background: var(--twui-paper-raised);
41
+ padding: 6px 16px;
42
+ font-family: var(--twui-font-mono);
43
+ font-size: 12px;
44
+ color: var(--twui-ink-soft);
45
+ }
46
+
47
+ .twui-tabcard-body {
48
+ display: flex;
49
+ flex: 1;
50
+ flex-direction: column;
51
+ border: 1px solid var(--twui-rule);
52
+ padding: 24px;
53
+ }
54
+
55
+ .twui-tabcard-note {
56
+ margin-top: auto;
57
+ margin-left: auto;
58
+ font-family: var(--twui-font-mono);
59
+ font-size: 12px;
60
+ color: var(--twui-ink-faint);
61
+ }
62
+ </style>
@@ -0,0 +1,10 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ title: string;
4
+ note?: string;
5
+ children: Snippet;
6
+ class?: string;
7
+ };
8
+ declare const TabCard: import("svelte").Component<$$ComponentProps, {}, "">;
9
+ type TabCard = ReturnType<typeof TabCard>;
10
+ export default TabCard;
@@ -0,0 +1,83 @@
1
+ <script lang="ts">
2
+ let {
3
+ items,
4
+ value = $bindable(''),
5
+ class: className = ''
6
+ }: {
7
+ items: { value: string; label: string; disabled?: boolean }[];
8
+ value?: string;
9
+ class?: string;
10
+ } = $props();
11
+
12
+ const firstEnabled = $derived(items.find((t) => !t.disabled));
13
+
14
+ function onKeydown(e: KeyboardEvent, index: number) {
15
+ if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;
16
+ e.preventDefault();
17
+ const dir = e.key === 'ArrowRight' ? 1 : -1;
18
+ let i = index + dir;
19
+ for (let steps = 0; steps < items.length; steps++, i += dir) {
20
+ const wrap = (i + items.length * Math.abs(dir)) % items.length;
21
+ const candidate = items[wrap];
22
+ if (!candidate.disabled) {
23
+ value = candidate.value;
24
+ return;
25
+ }
26
+ i = wrap;
27
+ }
28
+ }
29
+ </script>
30
+
31
+ <div class="twui-tabs {className}" role="tablist">
32
+ {#each items as tab, i (tab.value)}
33
+ <button
34
+ type="button"
35
+ role="tab"
36
+ aria-selected={tab.value === value}
37
+ tabindex={tab.value === value ? 0 : -1}
38
+ disabled={tab.disabled}
39
+ class="twui-tabs-item {tab.value === value ? 'twui-tabs-item-active' : ''}"
40
+ onclick={() => (value = tab.value)}
41
+ onkeydown={(e) => onKeydown(e, i)}
42
+ >
43
+ {tab.label}
44
+ </button>
45
+ {/each}
46
+ </div>
47
+
48
+ <style>
49
+ .twui-tabs {
50
+ display: flex;
51
+ flex-wrap: wrap;
52
+ gap: 4px 0;
53
+ border-bottom: 1px solid var(--twui-rule);
54
+ }
55
+
56
+ .twui-tabs-item {
57
+ padding: 8px 16px;
58
+ border: none;
59
+ border-bottom: 2px solid transparent;
60
+ background: transparent;
61
+ font-family: var(--twui-font-mono);
62
+ font-size: 13px;
63
+ color: var(--twui-ink-soft);
64
+ cursor: pointer;
65
+ transition:
66
+ color 0.15s ease,
67
+ border-color 0.15s ease;
68
+ }
69
+
70
+ .twui-tabs-item:hover:not(:disabled) {
71
+ color: var(--twui-accent);
72
+ }
73
+
74
+ .twui-tabs-item-active {
75
+ border-bottom-color: var(--twui-accent);
76
+ color: var(--twui-accent);
77
+ }
78
+
79
+ .twui-tabs-item:disabled {
80
+ opacity: 0.4;
81
+ cursor: not-allowed;
82
+ }
83
+ </style>
@@ -0,0 +1,12 @@
1
+ type $$ComponentProps = {
2
+ items: {
3
+ value: string;
4
+ label: string;
5
+ disabled?: boolean;
6
+ }[];
7
+ value?: string;
8
+ class?: string;
9
+ };
10
+ declare const Tabs: import("svelte").Component<$$ComponentProps, {}, "value">;
11
+ type Tabs = ReturnType<typeof Tabs>;
12
+ export default Tabs;
@@ -0,0 +1,118 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import { onMount } from 'svelte';
4
+
5
+ let {
6
+ labels = { light: 'Usar tema claro', dark: 'Usar tema escuro' },
7
+ icons,
8
+ showLabel = false,
9
+ label = { light: 'Tema claro', dark: 'Tema escuro' },
10
+ class: className = ''
11
+ }: {
12
+ labels?: { light: string; dark: string };
13
+ icons?: { sun: Snippet; moon: Snippet };
14
+ showLabel?: boolean;
15
+ label?: { light: string; dark: string };
16
+ class?: string;
17
+ } = $props();
18
+
19
+ let dark = $state(false);
20
+
21
+ onMount(() => {
22
+ const el = document.documentElement;
23
+ dark = el.getAttribute('data-theme') === 'dark' || el.classList.contains('dark');
24
+ });
25
+
26
+ function toggle() {
27
+ dark = !dark;
28
+ const el = document.documentElement;
29
+ el.setAttribute('data-theme', dark ? 'dark' : 'light');
30
+ el.classList.toggle('dark', dark);
31
+ localStorage.setItem('theme', dark ? 'dark' : 'light');
32
+ }
33
+ </script>
34
+
35
+ <button
36
+ type="button"
37
+ class="twui-theme-toggle {showLabel ? 'twui-theme-toggle-labeled' : ''} {className}"
38
+ aria-label={dark ? labels.light : labels.dark}
39
+ onclick={toggle}
40
+ >
41
+ {#if dark}
42
+ {#if icons?.sun}
43
+ {@render icons.sun()}
44
+ {:else}
45
+ <svg
46
+ class="twui-theme-toggle-icon"
47
+ viewBox="0 0 24 24"
48
+ fill="none"
49
+ stroke="currentColor"
50
+ stroke-width="1.75"
51
+ stroke-linecap="round"
52
+ stroke-linejoin="round"
53
+ aria-hidden="true"
54
+ >
55
+ <circle cx="12" cy="12" r="4"></circle>
56
+ <path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"></path>
57
+ </svg>
58
+ {/if}
59
+ {:else}
60
+ {#if icons?.moon}
61
+ {@render icons.moon()}
62
+ {:else}
63
+ <svg
64
+ class="twui-theme-toggle-icon"
65
+ viewBox="0 0 24 24"
66
+ fill="none"
67
+ stroke="currentColor"
68
+ stroke-width="1.75"
69
+ stroke-linecap="round"
70
+ stroke-linejoin="round"
71
+ aria-hidden="true"
72
+ >
73
+ <path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path>
74
+ </svg>
75
+ {/if}
76
+ {/if}
77
+ {#if showLabel}
78
+ <span class="twui-theme-toggle-label-text">{dark ? label.light : label.dark}</span>
79
+ {/if}
80
+ </button>
81
+
82
+ <style>
83
+ .twui-theme-toggle {
84
+ display: flex;
85
+ align-items: center;
86
+ justify-content: center;
87
+ width: 32px;
88
+ height: 32px;
89
+ border: none;
90
+ background: transparent;
91
+ color: var(--twui-ink-soft);
92
+ cursor: pointer;
93
+ transition: color 0.15s ease;
94
+ }
95
+
96
+ .twui-theme-toggle:hover {
97
+ color: var(--twui-accent);
98
+ }
99
+
100
+ .twui-theme-toggle-labeled {
101
+ width: auto;
102
+ height: auto;
103
+ gap: 8px;
104
+ padding: 6px 10px;
105
+ }
106
+
107
+ .twui-theme-toggle-label-text {
108
+ font-family: var(--twui-font-mono);
109
+ font-size: 14px;
110
+ line-height: 1;
111
+ white-space: nowrap;
112
+ }
113
+
114
+ .twui-theme-toggle-icon {
115
+ width: 16px;
116
+ height: 16px;
117
+ }
118
+ </style>