bref-ui 0.3.0 → 2.0.0
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.
- package/LICENSE +21 -0
- package/cli/commands/add/approve-overwrites.ts +17 -0
- package/cli/commands/add/display-changes.ts +11 -0
- package/cli/commands/add/index.ts +30 -0
- package/cli/commands/add/review-changes.ts +18 -0
- package/cli/commands/add/utils.ts +11 -0
- package/cli/commands/execute.ts +39 -0
- package/cli/commands/index.ts +19 -0
- package/cli/commands/init.ts +17 -0
- package/cli/commands/parse.ts +24 -0
- package/cli/commands/types.ts +2 -0
- package/cli/config/read/index.ts +15 -0
- package/cli/config/read/normalize-config.ts +21 -0
- package/cli/config/read/read-config-file.ts +13 -0
- package/cli/config/resolve/index.ts +20 -0
- package/cli/config/resolve/resolve-alias-target.ts +17 -0
- package/cli/config/resolve/resolve-alias.ts +17 -0
- package/cli/config/types.ts +5 -0
- package/cli/index.ts +4 -0
- package/cli/installation/copy/index.ts +25 -0
- package/cli/installation/copy/validate-overwrite-approvals.ts +18 -0
- package/cli/installation/copy/write-prepared-files.ts +26 -0
- package/cli/installation/exports/collect-exports.ts +19 -0
- package/cli/installation/exports/create-additions.ts +26 -0
- package/cli/installation/exports/index.ts +27 -0
- package/cli/installation/exports/merge-content.ts +12 -0
- package/cli/installation/exports/read-declared-export-names.ts +24 -0
- package/cli/installation/exports/read-exported-names.ts +21 -0
- package/cli/installation/exports/read-index.ts +14 -0
- package/cli/installation/exports/read-reexported-names.ts +24 -0
- package/cli/installation/exports/types.ts +10 -0
- package/cli/installation/exports/utils.ts +54 -0
- package/cli/installation/index.ts +35 -0
- package/cli/installation/parser/index.ts +29 -0
- package/cli/installation/parser/types.ts +12 -0
- package/cli/installation/parser/utils.ts +45 -0
- package/cli/installation/prepare/collect-source-files.ts +15 -0
- package/cli/installation/prepare/index.ts +15 -0
- package/cli/installation/prepare/read-source-files.ts +21 -0
- package/cli/installation/prepare/rewrite-imports.ts +50 -0
- package/cli/installation/prepare/rewrite-source.ts +36 -0
- package/cli/installation/prepare/types.ts +7 -0
- package/cli/installation/preview/compare-prepared-files.ts +18 -0
- package/cli/installation/preview/index.ts +18 -0
- package/cli/installation/preview/read-destination-files.ts +25 -0
- package/cli/installation/preview/types.ts +9 -0
- package/cli/installation/types.ts +15 -0
- package/cli/pack.ts +6 -0
- package/cli/registry/load/create-registry.ts +25 -0
- package/cli/registry/load/discover-manifests.ts +9 -0
- package/cli/registry/load/index.ts +21 -0
- package/cli/registry/load/load-entry.ts +22 -0
- package/cli/registry/load/utils.ts +70 -0
- package/cli/registry/load/validate-dependencies.ts +33 -0
- package/cli/registry/plan/collect-entries.ts +28 -0
- package/cli/registry/plan/index.ts +14 -0
- package/cli/registry/types.ts +17 -0
- package/dist/button/button.svelte +126 -0
- package/dist/button/button.svelte.d.ts +4 -0
- package/dist/button/registry.json +6 -0
- package/dist/button/types.d.ts +32 -0
- package/dist/checkbox/checkbox.svelte +143 -0
- package/dist/checkbox/checkbox.svelte.d.ts +4 -0
- package/dist/checkbox/registry.json +6 -0
- package/dist/checkbox/types.d.ts +6 -0
- package/dist/combobox/combobox.svelte +156 -0
- package/dist/combobox/combobox.svelte.d.ts +4 -0
- package/dist/combobox/form.svelte +61 -0
- package/dist/combobox/form.svelte.d.ts +4 -0
- package/dist/combobox/input.svelte +132 -0
- package/dist/combobox/input.svelte.d.ts +4 -0
- package/dist/combobox/list.svelte +78 -0
- package/dist/combobox/list.svelte.d.ts +4 -0
- package/dist/combobox/option.svelte +77 -0
- package/dist/combobox/option.svelte.d.ts +4 -0
- package/dist/combobox/registry.json +6 -0
- package/dist/combobox/types.d.ts +61 -0
- package/dist/dialog/dialog.svelte +182 -0
- package/dist/dialog/dialog.svelte.d.ts +4 -0
- package/dist/dialog/footer.svelte +26 -0
- package/dist/dialog/footer.svelte.d.ts +7 -0
- package/dist/dialog/header.svelte +56 -0
- package/dist/dialog/header.svelte.d.ts +4 -0
- package/dist/dialog/registry.json +6 -0
- package/dist/dialog/types.d.ts +31 -0
- package/dist/icon/icon.svelte +108 -0
- package/dist/icon/icon.svelte.d.ts +4 -0
- package/dist/icon/names.d.ts +7 -0
- package/dist/icon/registry.json +6 -0
- package/dist/icon/types.d.ts +16 -0
- package/dist/index.d.ts +20 -2
- package/dist/index.js +20 -2
- package/dist/pill/content.svelte +23 -0
- package/dist/pill/content.svelte.d.ts +4 -0
- package/dist/pill/on-delete.svelte +26 -0
- package/dist/pill/on-delete.svelte.d.ts +4 -0
- package/dist/pill/pill.svelte +200 -0
- package/dist/{base/pill → pill}/pill.svelte.d.ts +1 -1
- package/dist/pill/registry.json +6 -0
- package/dist/pill/types.d.ts +19 -0
- package/dist/pill-choice-group/pill-choice-group.svelte +131 -0
- package/dist/pill-choice-group/pill-choice-group.svelte.d.ts +4 -0
- package/dist/pill-choice-group/registry.json +6 -0
- package/dist/pill-choice-group/types.d.ts +13 -0
- package/dist/pill-group/container.svelte +40 -0
- package/dist/pill-group/container.svelte.d.ts +4 -0
- package/dist/pill-group/pill-group.svelte +27 -0
- package/dist/pill-group/pill-group.svelte.d.ts +4 -0
- package/dist/pill-group/registry.json +6 -0
- package/dist/pill-group/types.d.ts +13 -0
- package/dist/popover/popover.svelte +86 -0
- package/dist/popover/popover.svelte.d.ts +4 -0
- package/dist/popover/registry.json +6 -0
- package/dist/popover/types.d.ts +8 -0
- package/dist/progress/progress.svelte +256 -0
- package/dist/progress/progress.svelte.d.ts +4 -0
- package/dist/progress/registry.json +6 -0
- package/dist/progress/types.d.ts +11 -0
- package/dist/select/empty.svelte +25 -0
- package/dist/select/empty.svelte.d.ts +4 -0
- package/dist/select/list.svelte +27 -0
- package/dist/select/list.svelte.d.ts +4 -0
- package/dist/select/option.svelte +64 -0
- package/dist/select/option.svelte.d.ts +4 -0
- package/dist/select/registry.json +6 -0
- package/dist/select/select.svelte +70 -0
- package/dist/{base/select → select}/select.svelte.d.ts +2 -2
- package/dist/select/trigger.svelte +86 -0
- package/dist/select/trigger.svelte.d.ts +4 -0
- package/dist/select/types.d.ts +31 -0
- package/dist/select/types.js +1 -0
- package/dist/spinner/registry.json +6 -0
- package/dist/spinner/spinner.svelte +114 -0
- package/dist/spinner/spinner.svelte.d.ts +4 -0
- package/dist/spinner/types.d.ts +6 -0
- package/dist/spinner/types.js +1 -0
- package/dist/surface/registry.json +6 -0
- package/dist/surface/surface.svelte +96 -0
- package/dist/surface/surface.svelte.d.ts +4 -0
- package/dist/surface/types.d.ts +25 -0
- package/dist/surface/types.js +1 -0
- package/dist/switch/registry.json +6 -0
- package/dist/switch/switch.svelte +162 -0
- package/dist/switch/switch.svelte.d.ts +4 -0
- package/dist/switch/types.d.ts +8 -0
- package/dist/switch/types.js +1 -0
- package/dist/text-area/registry.json +8 -0
- package/dist/text-area/text-area.svelte +186 -0
- package/dist/text-area/text-area.svelte.d.ts +4 -0
- package/dist/text-area/types.d.ts +12 -0
- package/dist/text-area/types.js +1 -0
- package/dist/text-input/registry.json +8 -0
- package/dist/text-input/text-input.svelte +189 -0
- package/dist/text-input/text-input.svelte.d.ts +4 -0
- package/dist/text-input/types.d.ts +11 -0
- package/dist/text-input/types.js +1 -0
- package/dist/theme/cli-theme.svelte +16 -0
- package/dist/theme/cli-theme.svelte.d.ts +7 -0
- package/dist/theme/colors.svelte +102 -0
- package/dist/theme/colors.svelte.d.ts +4 -0
- package/dist/theme/fonts.svelte +10 -0
- package/dist/theme/fonts.svelte.d.ts +26 -0
- package/dist/theme/registry.json +13 -0
- package/dist/theme/styles.svelte +50 -0
- package/dist/theme/styles.svelte.d.ts +26 -0
- package/dist/theme/surface.d.ts +3 -0
- package/dist/theme/surface.js +10 -0
- package/dist/theme/surfaces.svelte +208 -0
- package/dist/theme/surfaces.svelte.d.ts +18 -0
- package/dist/theme/theme-mode-toggle.svelte +9 -0
- package/dist/theme/theme-mode-toggle.svelte.d.ts +4 -0
- package/dist/theme/theme.svelte +16 -0
- package/dist/theme/theme.svelte.d.ts +4 -0
- package/dist/theme/types.d.ts +17 -0
- package/dist/theme/types.js +1 -0
- package/dist/tree-view/registry.json +15 -0
- package/dist/tree-view/tree-node/chevron-button.svelte +56 -0
- package/dist/tree-view/tree-node/chevron-button.svelte.d.ts +4 -0
- package/dist/tree-view/tree-node/content.svelte +62 -0
- package/dist/tree-view/tree-node/content.svelte.d.ts +4 -0
- package/dist/tree-view/tree-node/delete-button.svelte +52 -0
- package/dist/tree-view/tree-node/delete-button.svelte.d.ts +4 -0
- package/dist/tree-view/tree-node/tree-node.svelte +111 -0
- package/dist/{base/tree-view → tree-view/tree-node}/tree-node.svelte.d.ts +2 -3
- package/dist/tree-view/tree-view-section.svelte +42 -0
- package/dist/tree-view/tree-view-section.svelte.d.ts +4 -0
- package/dist/tree-view/tree-view.svelte +65 -0
- package/dist/{base/tree-view → tree-view}/tree-view.svelte.d.ts +2 -2
- package/dist/tree-view/types.d.ts +31 -0
- package/dist/tree-view/types.js +1 -0
- package/dist/types.d.ts +25 -0
- package/dist/types.js +1 -0
- package/package.json +39 -45
- package/readme.md +157 -0
- package/src/lib/button/button.svelte +126 -0
- package/src/lib/button/registry.json +6 -0
- package/src/lib/button/types.ts +42 -0
- package/src/lib/checkbox/checkbox.svelte +143 -0
- package/src/lib/checkbox/registry.json +6 -0
- package/src/lib/checkbox/types.ts +7 -0
- package/src/lib/combobox/combobox.svelte +156 -0
- package/src/lib/combobox/form.svelte +61 -0
- package/src/lib/combobox/input.svelte +132 -0
- package/src/lib/combobox/list.svelte +78 -0
- package/src/lib/combobox/option.svelte +77 -0
- package/src/lib/combobox/registry.json +6 -0
- package/src/lib/combobox/types.ts +89 -0
- package/src/lib/dialog/dialog.svelte +182 -0
- package/src/lib/dialog/footer.svelte +26 -0
- package/src/lib/dialog/header.svelte +56 -0
- package/src/lib/dialog/registry.json +6 -0
- package/src/lib/dialog/types.ts +35 -0
- package/src/lib/icon/icon.svelte +108 -0
- package/src/lib/icon/names.ts +3794 -0
- package/src/lib/icon/registry.json +6 -0
- package/src/lib/icon/types.ts +18 -0
- package/src/lib/index.ts +20 -0
- package/src/lib/pill/content.svelte +23 -0
- package/src/lib/pill/on-delete.svelte +26 -0
- package/src/lib/pill/pill.svelte +200 -0
- package/src/lib/pill/registry.json +6 -0
- package/src/lib/pill/types.ts +22 -0
- package/src/lib/pill-choice-group/pill-choice-group.svelte +131 -0
- package/src/lib/pill-choice-group/registry.json +6 -0
- package/src/lib/pill-choice-group/types.ts +14 -0
- package/src/lib/pill-group/container.svelte +40 -0
- package/src/lib/pill-group/pill-group.svelte +27 -0
- package/src/lib/pill-group/registry.json +6 -0
- package/src/lib/pill-group/types.ts +15 -0
- package/src/lib/popover/popover.svelte +86 -0
- package/src/lib/popover/registry.json +6 -0
- package/src/lib/popover/types.ts +9 -0
- package/src/lib/progress/progress.svelte +256 -0
- package/src/lib/progress/registry.json +6 -0
- package/src/lib/progress/types.ts +15 -0
- package/src/lib/select/empty.svelte +25 -0
- package/src/lib/select/list.svelte +27 -0
- package/src/lib/select/option.svelte +64 -0
- package/src/lib/select/registry.json +6 -0
- package/src/lib/select/select.svelte +70 -0
- package/src/lib/select/trigger.svelte +86 -0
- package/src/lib/select/types.ts +41 -0
- package/src/lib/spinner/registry.json +6 -0
- package/src/lib/spinner/spinner.svelte +114 -0
- package/src/lib/spinner/types.ts +7 -0
- package/src/lib/surface/registry.json +6 -0
- package/src/lib/surface/surface.svelte +96 -0
- package/src/lib/surface/types.ts +28 -0
- package/src/lib/switch/registry.json +6 -0
- package/src/lib/switch/switch.svelte +162 -0
- package/src/lib/switch/types.ts +12 -0
- package/src/lib/text-area/registry.json +8 -0
- package/src/lib/text-area/text-area.svelte +186 -0
- package/src/lib/text-area/types.ts +13 -0
- package/src/lib/text-input/registry.json +8 -0
- package/src/lib/text-input/text-input.svelte +189 -0
- package/src/lib/text-input/types.ts +12 -0
- package/src/lib/theme/cli-theme.svelte +16 -0
- package/src/lib/theme/colors.svelte +102 -0
- package/src/lib/theme/fonts.svelte +10 -0
- package/src/lib/theme/registry.json +13 -0
- package/src/lib/theme/styles.svelte +50 -0
- package/src/lib/theme/surface.ts +18 -0
- package/src/lib/theme/surfaces.svelte +208 -0
- package/src/lib/theme/theme-mode-toggle.svelte +9 -0
- package/src/lib/theme/theme.svelte +16 -0
- package/src/lib/theme/types.ts +18 -0
- package/src/lib/tree-view/registry.json +15 -0
- package/src/lib/tree-view/tree-node/chevron-button.svelte +56 -0
- package/src/lib/tree-view/tree-node/content.svelte +62 -0
- package/src/lib/tree-view/tree-node/delete-button.svelte +52 -0
- package/src/lib/tree-view/tree-node/tree-node.svelte +111 -0
- package/src/lib/tree-view/tree-view-section.svelte +42 -0
- package/src/lib/tree-view/tree-view.svelte +65 -0
- package/src/lib/tree-view/types.ts +39 -0
- package/src/lib/types.ts +45 -0
- package/README.md +0 -110
- package/dist/base/button/button.svelte +0 -260
- package/dist/base/button/button.svelte.d.ts +0 -6
- package/dist/base/button/icon-button.svelte +0 -226
- package/dist/base/button/icon-button.svelte.d.ts +0 -6
- package/dist/base/button/index.d.ts +0 -2
- package/dist/base/button/index.js +0 -2
- package/dist/base/button/types.d.ts +0 -17
- package/dist/base/icon/icon.svelte +0 -118
- package/dist/base/icon/icon.svelte.d.ts +0 -7
- package/dist/base/icon/index.d.ts +0 -2
- package/dist/base/icon/index.js +0 -2
- package/dist/base/icon/types.d.ts +0 -10
- package/dist/base/index.d.ts +0 -12
- package/dist/base/index.js +0 -12
- package/dist/base/loading/circular-loading.svelte +0 -95
- package/dist/base/loading/circular-loading.svelte.d.ts +0 -4
- package/dist/base/loading/index.d.ts +0 -4
- package/dist/base/loading/index.js +0 -4
- package/dist/base/loading/morphing-shapes-loading.svelte +0 -241
- package/dist/base/loading/morphing-shapes-loading.svelte.d.ts +0 -4
- package/dist/base/loading/pulsing-dots-loading.svelte +0 -115
- package/dist/base/loading/pulsing-dots-loading.svelte.d.ts +0 -4
- package/dist/base/loading/textual-loading.svelte +0 -179
- package/dist/base/loading/textual-loading.svelte.d.ts +0 -4
- package/dist/base/loading/types.d.ts +0 -16
- package/dist/base/pill/index.d.ts +0 -1
- package/dist/base/pill/index.js +0 -1
- package/dist/base/pill/pill.svelte +0 -146
- package/dist/base/pill/types.d.ts +0 -9
- package/dist/base/progress-bar/index.d.ts +0 -1
- package/dist/base/progress-bar/index.js +0 -1
- package/dist/base/progress-bar/progress-bar.svelte +0 -174
- package/dist/base/progress-bar/progress-bar.svelte.d.ts +0 -4
- package/dist/base/progress-bar/types.d.ts +0 -9
- package/dist/base/select/index.d.ts +0 -2
- package/dist/base/select/index.js +0 -2
- package/dist/base/select/select.svelte +0 -145
- package/dist/base/select/types.d.ts +0 -16
- package/dist/base/slider/index.d.ts +0 -1
- package/dist/base/slider/index.js +0 -1
- package/dist/base/slider/slider.svelte +0 -192
- package/dist/base/slider/slider.svelte.d.ts +0 -6
- package/dist/base/slider/types.d.ts +0 -12
- package/dist/base/text-input/area-text-input.svelte +0 -105
- package/dist/base/text-input/area-text-input.svelte.d.ts +0 -6
- package/dist/base/text-input/index.d.ts +0 -2
- package/dist/base/text-input/index.js +0 -2
- package/dist/base/text-input/text-input.svelte +0 -213
- package/dist/base/text-input/text-input.svelte.d.ts +0 -6
- package/dist/base/text-input/types.d.ts +0 -27
- package/dist/base/theme/color-tokens.d.ts +0 -36
- package/dist/base/theme/color-tokens.js +0 -105
- package/dist/base/theme/index.d.ts +0 -3
- package/dist/base/theme/index.js +0 -3
- package/dist/base/theme/mode.d.ts +0 -3
- package/dist/base/theme/mode.js +0 -14
- package/dist/base/theme/theme.svelte +0 -87
- package/dist/base/theme/theme.svelte.d.ts +0 -3
- package/dist/base/theme/types.d.ts +0 -27
- package/dist/base/theme/types.js +0 -20
- package/dist/base/toggle/index.d.ts +0 -1
- package/dist/base/toggle/index.js +0 -1
- package/dist/base/toggle/toggle.svelte +0 -109
- package/dist/base/toggle/toggle.svelte.d.ts +0 -4
- package/dist/base/toggle/types.d.ts +0 -7
- package/dist/base/tree-view/index.d.ts +0 -3
- package/dist/base/tree-view/index.js +0 -3
- package/dist/base/tree-view/tree-node.svelte +0 -132
- package/dist/base/tree-view/tree-view.svelte +0 -56
- package/dist/base/tree-view/types.d.ts +0 -23
- package/dist/base/types.d.ts +0 -4
- /package/dist/{base/button → button}/types.js +0 -0
- /package/dist/{base/icon → checkbox}/types.js +0 -0
- /package/dist/{base/loading → combobox}/types.js +0 -0
- /package/dist/{base/pill → dialog}/types.js +0 -0
- /package/dist/{base/progress-bar/types.js → icon/names.js} +0 -0
- /package/dist/{base/select → icon}/types.js +0 -0
- /package/dist/{base/toggle → pill}/types.js +0 -0
- /package/dist/{base/slider → pill-choice-group}/types.js +0 -0
- /package/dist/{base/text-input → pill-group}/types.js +0 -0
- /package/dist/{base/tree-view → popover}/types.js +0 -0
- /package/dist/{base → progress}/types.js +0 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
3
|
+
import Icon from '../../icon/icon.svelte';
|
|
4
|
+
|
|
5
|
+
let attributes: HTMLButtonAttributes = $props();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<button {...attributes} type="button">
|
|
9
|
+
<span><Icon name="chevron_right" /></span>
|
|
10
|
+
</button>
|
|
11
|
+
|
|
12
|
+
<style>
|
|
13
|
+
* {
|
|
14
|
+
transition: all 150ms;
|
|
15
|
+
}
|
|
16
|
+
button {
|
|
17
|
+
position: relative;
|
|
18
|
+
z-index: 1;
|
|
19
|
+
display: inline-flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
min-width: var(--tree-action-size);
|
|
23
|
+
min-height: var(--tree-action-size);
|
|
24
|
+
padding: 0.25rem 0.5rem;
|
|
25
|
+
border: 0;
|
|
26
|
+
border-radius: 999px;
|
|
27
|
+
background: transparent;
|
|
28
|
+
color: inherit;
|
|
29
|
+
font: inherit;
|
|
30
|
+
cursor: pointer;
|
|
31
|
+
}
|
|
32
|
+
span {
|
|
33
|
+
display: inline-flex;
|
|
34
|
+
font-size: 1.25em;
|
|
35
|
+
}
|
|
36
|
+
button[aria-expanded='true'] span {
|
|
37
|
+
transform: rotate(90deg);
|
|
38
|
+
}
|
|
39
|
+
button:not(:disabled):hover {
|
|
40
|
+
background: color-mix(in srgb, var(--color-primary) 12%, transparent);
|
|
41
|
+
}
|
|
42
|
+
button:focus-visible {
|
|
43
|
+
outline: 2px solid var(--color-primary);
|
|
44
|
+
outline-offset: -2px;
|
|
45
|
+
}
|
|
46
|
+
@media (prefers-reduced-motion: reduce) {
|
|
47
|
+
* {
|
|
48
|
+
transition: none;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
@media (forced-colors: active) {
|
|
52
|
+
button:focus-visible {
|
|
53
|
+
outline-color: Highlight;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
</style>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Icon from '../../icon/icon.svelte';
|
|
3
|
+
import type { TreeNodeContentProps } from '../types.js';
|
|
4
|
+
|
|
5
|
+
let { item, ...attributes }: TreeNodeContentProps = $props();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<button {...attributes} type="button" disabled={item.disabled}>
|
|
9
|
+
{#if item.icon}<Icon {...item.icon} label={undefined} />{/if}
|
|
10
|
+
<span>{item.label}</span>
|
|
11
|
+
</button>
|
|
12
|
+
|
|
13
|
+
<style>
|
|
14
|
+
* {
|
|
15
|
+
transition: all 150ms;
|
|
16
|
+
}
|
|
17
|
+
button {
|
|
18
|
+
display: inline-flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
justify-content: start;
|
|
21
|
+
flex: 1;
|
|
22
|
+
gap: 0.5rem;
|
|
23
|
+
min-width: 0;
|
|
24
|
+
min-height: var(--tree-action-size);
|
|
25
|
+
padding: 0.25rem 0.5rem;
|
|
26
|
+
border: 0;
|
|
27
|
+
border-radius: 999px;
|
|
28
|
+
outline: none;
|
|
29
|
+
background: transparent;
|
|
30
|
+
color: inherit;
|
|
31
|
+
font: inherit;
|
|
32
|
+
text-align: start;
|
|
33
|
+
cursor: pointer;
|
|
34
|
+
}
|
|
35
|
+
button::before {
|
|
36
|
+
position: absolute;
|
|
37
|
+
inset: 0;
|
|
38
|
+
border-radius: inherit;
|
|
39
|
+
content: '';
|
|
40
|
+
}
|
|
41
|
+
button:focus-visible::before {
|
|
42
|
+
outline: 2px solid var(--color-primary);
|
|
43
|
+
outline-offset: -2px;
|
|
44
|
+
}
|
|
45
|
+
button:disabled {
|
|
46
|
+
color: var(--color-muted);
|
|
47
|
+
cursor: default;
|
|
48
|
+
}
|
|
49
|
+
@media (prefers-reduced-motion: reduce) {
|
|
50
|
+
* {
|
|
51
|
+
transition: none;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
@media (forced-colors: active) {
|
|
55
|
+
button:disabled {
|
|
56
|
+
color: GrayText;
|
|
57
|
+
}
|
|
58
|
+
button:focus-visible::before {
|
|
59
|
+
outline-color: Highlight;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
</style>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
3
|
+
import Icon from '../../icon/icon.svelte';
|
|
4
|
+
|
|
5
|
+
let attributes: HTMLButtonAttributes = $props();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<button {...attributes} type="button"><Icon name="close" /></button>
|
|
9
|
+
|
|
10
|
+
<style>
|
|
11
|
+
button {
|
|
12
|
+
position: relative;
|
|
13
|
+
z-index: 1;
|
|
14
|
+
display: inline-flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
justify-content: center;
|
|
17
|
+
min-width: var(--tree-action-size);
|
|
18
|
+
min-height: var(--tree-action-size);
|
|
19
|
+
padding: 0.25rem 0.5rem;
|
|
20
|
+
border: 0;
|
|
21
|
+
border-radius: 999px;
|
|
22
|
+
background: transparent;
|
|
23
|
+
color: inherit;
|
|
24
|
+
font: inherit;
|
|
25
|
+
cursor: pointer;
|
|
26
|
+
transition: all 150ms;
|
|
27
|
+
}
|
|
28
|
+
button:not(:disabled):hover {
|
|
29
|
+
background: color-mix(in srgb, var(--color-primary) 12%, transparent);
|
|
30
|
+
}
|
|
31
|
+
button:focus-visible {
|
|
32
|
+
outline: 2px solid var(--color-primary);
|
|
33
|
+
outline-offset: -2px;
|
|
34
|
+
}
|
|
35
|
+
button:disabled {
|
|
36
|
+
color: var(--color-muted);
|
|
37
|
+
cursor: default;
|
|
38
|
+
}
|
|
39
|
+
@media (prefers-reduced-motion: reduce) {
|
|
40
|
+
button {
|
|
41
|
+
transition: none;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
@media (forced-colors: active) {
|
|
45
|
+
button:disabled {
|
|
46
|
+
color: GrayText;
|
|
47
|
+
}
|
|
48
|
+
button:focus-visible {
|
|
49
|
+
outline-color: Highlight;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
</style>
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { prefersReducedMotion } from 'svelte/motion';
|
|
3
|
+
import { fly } from 'svelte/transition';
|
|
4
|
+
import ChevronButton from './chevron-button.svelte';
|
|
5
|
+
import DeleteButton from './delete-button.svelte';
|
|
6
|
+
import Content from './content.svelte';
|
|
7
|
+
import RecursiveNode from './tree-node.svelte';
|
|
8
|
+
import type { TreeNodeProps } from '../types.js';
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
item,
|
|
12
|
+
selection = $bindable(),
|
|
13
|
+
defaultExpanded = false,
|
|
14
|
+
onDelete,
|
|
15
|
+
indent = 0
|
|
16
|
+
}: TreeNodeProps = $props();
|
|
17
|
+
|
|
18
|
+
// svelte-ignore state_referenced_locally
|
|
19
|
+
let expanded = $state(defaultExpanded);
|
|
20
|
+
const childrenId = $props.id();
|
|
21
|
+
|
|
22
|
+
const selected = $derived(
|
|
23
|
+
Array.isArray(selection) ? selection.includes(item.id) : selection === item.id
|
|
24
|
+
);
|
|
25
|
+
const select = () => {
|
|
26
|
+
selection = Array.isArray(selection)
|
|
27
|
+
? selected
|
|
28
|
+
? selection.filter((id) => id !== item.id)
|
|
29
|
+
: [...selection, item.id]
|
|
30
|
+
: item.id;
|
|
31
|
+
};
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<div
|
|
35
|
+
in:fly|global={{ y: -4, duration: prefersReducedMotion.current ? 0 : 150 }}
|
|
36
|
+
data-selected={selected}
|
|
37
|
+
data-disabled={item.disabled}
|
|
38
|
+
style:padding-left={`calc(0.25rem + ${indent * 1.25}rem)`}
|
|
39
|
+
>
|
|
40
|
+
{#if item.children?.length}
|
|
41
|
+
<ChevronButton
|
|
42
|
+
aria-label={`Children of ${item.label}`}
|
|
43
|
+
aria-expanded={expanded}
|
|
44
|
+
aria-controls={childrenId}
|
|
45
|
+
onclick={() => (expanded = !expanded)}
|
|
46
|
+
/>
|
|
47
|
+
{:else}
|
|
48
|
+
<span data-spacer aria-hidden="true"></span>
|
|
49
|
+
{/if}
|
|
50
|
+
<Content {item} aria-pressed={selected} onclick={select} />
|
|
51
|
+
{#if onDelete}
|
|
52
|
+
<DeleteButton
|
|
53
|
+
aria-label={`Delete ${item.label}`}
|
|
54
|
+
disabled={item.disabled}
|
|
55
|
+
onclick={() => onDelete?.(item.id)}
|
|
56
|
+
/>
|
|
57
|
+
{/if}
|
|
58
|
+
</div>
|
|
59
|
+
{#if item.children?.length}
|
|
60
|
+
<div role="group" id={childrenId} hidden={!expanded}>
|
|
61
|
+
{#each item.children as child (child.id)}
|
|
62
|
+
<RecursiveNode indent={indent + 1} item={child} bind:selection {defaultExpanded} {onDelete} />
|
|
63
|
+
{/each}
|
|
64
|
+
</div>
|
|
65
|
+
{/if}
|
|
66
|
+
|
|
67
|
+
<style>
|
|
68
|
+
* {
|
|
69
|
+
transition: all 150ms;
|
|
70
|
+
}
|
|
71
|
+
div[data-selected] {
|
|
72
|
+
box-sizing: border-box;
|
|
73
|
+
position: relative;
|
|
74
|
+
display: flex;
|
|
75
|
+
align-items: center;
|
|
76
|
+
gap: 0.25rem;
|
|
77
|
+
min-height: var(--tree-height);
|
|
78
|
+
padding: 0.125rem 0.25rem;
|
|
79
|
+
border: 1px solid transparent;
|
|
80
|
+
border-radius: 999px;
|
|
81
|
+
overflow-wrap: anywhere;
|
|
82
|
+
}
|
|
83
|
+
[data-spacer] {
|
|
84
|
+
flex: 0 0 var(--tree-action-size);
|
|
85
|
+
}
|
|
86
|
+
div[role='group'] {
|
|
87
|
+
display: contents;
|
|
88
|
+
}
|
|
89
|
+
div[hidden] {
|
|
90
|
+
display: none;
|
|
91
|
+
}
|
|
92
|
+
div[data-selected='true'] {
|
|
93
|
+
border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
|
|
94
|
+
background: color-mix(in srgb, var(--color-primary) 16%, transparent);
|
|
95
|
+
color: var(--color-primary);
|
|
96
|
+
}
|
|
97
|
+
div[data-selected='false']:not([data-disabled='true']):hover {
|
|
98
|
+
background: color-mix(in srgb, var(--color-primary) 12%, transparent);
|
|
99
|
+
}
|
|
100
|
+
@media (prefers-reduced-motion: reduce) {
|
|
101
|
+
* {
|
|
102
|
+
transition: none;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
@media (forced-colors: active) {
|
|
106
|
+
div[data-selected='true'] {
|
|
107
|
+
border-color: Highlight;
|
|
108
|
+
color: Highlight;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
</style>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Icon from '../icon/icon.svelte';
|
|
3
|
+
import type { TreeSectionProps } from './types.js';
|
|
4
|
+
|
|
5
|
+
let { label, description, icon }: TreeSectionProps = $props();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<header>
|
|
9
|
+
<div>
|
|
10
|
+
{#if icon}<Icon {...icon} label={undefined} />{/if}
|
|
11
|
+
<span>{label}</span>
|
|
12
|
+
</div>
|
|
13
|
+
{#if description}<p>{description}</p>{/if}
|
|
14
|
+
</header>
|
|
15
|
+
|
|
16
|
+
<style>
|
|
17
|
+
header {
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
align-items: flex-start;
|
|
21
|
+
gap: 0.25rem;
|
|
22
|
+
padding: 0.75rem 0.5rem 0.25rem;
|
|
23
|
+
color: var(--color-muted);
|
|
24
|
+
font-size: 0.8em;
|
|
25
|
+
font-weight: 600;
|
|
26
|
+
letter-spacing: 0.06em;
|
|
27
|
+
text-transform: uppercase;
|
|
28
|
+
overflow-wrap: anywhere;
|
|
29
|
+
}
|
|
30
|
+
div {
|
|
31
|
+
display: flex;
|
|
32
|
+
align-items: center;
|
|
33
|
+
gap: 0.5rem;
|
|
34
|
+
min-width: 0;
|
|
35
|
+
}
|
|
36
|
+
p {
|
|
37
|
+
margin: 0;
|
|
38
|
+
font-weight: 400;
|
|
39
|
+
letter-spacing: normal;
|
|
40
|
+
text-transform: none;
|
|
41
|
+
}
|
|
42
|
+
</style>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import TreeNode from './tree-node/tree-node.svelte';
|
|
3
|
+
import TreeViewSection from './tree-view-section.svelte';
|
|
4
|
+
import type { TreeViewProps } from './types.js';
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
items,
|
|
8
|
+
sections = [],
|
|
9
|
+
label = 'Tree view',
|
|
10
|
+
size = 'medium',
|
|
11
|
+
selection = $bindable(),
|
|
12
|
+
defaultExpanded = false,
|
|
13
|
+
onDelete,
|
|
14
|
+
node
|
|
15
|
+
}: TreeViewProps = $props();
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
{#snippet nodes(items: TreeViewProps['items'])}
|
|
19
|
+
<div data-nodes>
|
|
20
|
+
{#each items as item (item.id)}
|
|
21
|
+
{#if node}
|
|
22
|
+
{@render node(item)}
|
|
23
|
+
{:else}
|
|
24
|
+
<TreeNode {item} bind:selection {defaultExpanded} {onDelete} />
|
|
25
|
+
{/if}
|
|
26
|
+
{/each}
|
|
27
|
+
</div>
|
|
28
|
+
{/snippet}
|
|
29
|
+
|
|
30
|
+
<div role="group" aria-label={label} data-size={size}>
|
|
31
|
+
{@render nodes(items)}
|
|
32
|
+
{#each sections as section (section.id)}
|
|
33
|
+
<section aria-label={section.label}>
|
|
34
|
+
<TreeViewSection {...section} />
|
|
35
|
+
{@render nodes(section.items)}
|
|
36
|
+
</section>
|
|
37
|
+
{/each}
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<style>
|
|
41
|
+
div {
|
|
42
|
+
--tree-height: 2.75rem;
|
|
43
|
+
--tree-action-size: 2.25rem;
|
|
44
|
+
display: grid;
|
|
45
|
+
gap: 0.375rem;
|
|
46
|
+
min-width: 0;
|
|
47
|
+
color: var(--color-foreground);
|
|
48
|
+
font: inherit;
|
|
49
|
+
}
|
|
50
|
+
div[data-size='small'] {
|
|
51
|
+
--tree-height: 2.5rem;
|
|
52
|
+
--tree-action-size: 2rem;
|
|
53
|
+
font-size: 0.875rem;
|
|
54
|
+
}
|
|
55
|
+
div[data-size='large'] {
|
|
56
|
+
--tree-height: 3.25rem;
|
|
57
|
+
--tree-action-size: 2.5rem;
|
|
58
|
+
font-size: 1.125rem;
|
|
59
|
+
}
|
|
60
|
+
div[data-nodes] {
|
|
61
|
+
display: flex;
|
|
62
|
+
flex-direction: column;
|
|
63
|
+
gap: 0.25rem;
|
|
64
|
+
}
|
|
65
|
+
</style>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
3
|
+
import type { BaseSize, IconProps } from '../types.js';
|
|
4
|
+
|
|
5
|
+
export interface TreeItemProps {
|
|
6
|
+
id: string;
|
|
7
|
+
label: string;
|
|
8
|
+
icon?: Omit<IconProps, 'label' | 'size' | 'color'>;
|
|
9
|
+
children?: TreeItemProps[];
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface TreeSectionProps extends Pick<TreeItemProps, 'id' | 'label' | 'icon'> {
|
|
14
|
+
description?: string;
|
|
15
|
+
items: TreeItemProps[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface TreeViewProps {
|
|
19
|
+
items: TreeItemProps[];
|
|
20
|
+
sections?: TreeSectionProps[];
|
|
21
|
+
label?: string;
|
|
22
|
+
size?: BaseSize;
|
|
23
|
+
selection?: string | string[];
|
|
24
|
+
defaultExpanded?: boolean;
|
|
25
|
+
onDelete?: (id: string) => void;
|
|
26
|
+
node?: Snippet<[TreeItemProps]>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface TreeNodeProps extends Pick<
|
|
30
|
+
TreeViewProps,
|
|
31
|
+
'selection' | 'defaultExpanded' | 'onDelete'
|
|
32
|
+
> {
|
|
33
|
+
item: TreeItemProps;
|
|
34
|
+
indent?: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface TreeNodeContentProps extends HTMLButtonAttributes {
|
|
38
|
+
item: TreeItemProps;
|
|
39
|
+
}
|
package/src/lib/types.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export type BaseSize = 'small' | 'medium' | 'large';
|
|
2
|
+
export type Size = 'x-small' | BaseSize | 'x-large';
|
|
3
|
+
export type Variant = 'neutral' | 'soft' | 'filled';
|
|
4
|
+
export type StatusColor = 'info' | 'success' | 'warning' | 'error';
|
|
5
|
+
export type Color = 'primary' | 'secondary' | 'foreground' | 'background' | 'muted' | StatusColor;
|
|
6
|
+
export type Orientation = 'horizontal' | 'vertical';
|
|
7
|
+
export type Dimension = 'fit' | 'fill';
|
|
8
|
+
|
|
9
|
+
export type { ButtonProps } from './button/types.js';
|
|
10
|
+
export type {
|
|
11
|
+
ComboboxProps,
|
|
12
|
+
ComboboxNativeProps,
|
|
13
|
+
ComboboxInputProps,
|
|
14
|
+
ComboboxListProps,
|
|
15
|
+
ComboboxOptionProps,
|
|
16
|
+
ComboboxFormProps
|
|
17
|
+
} from './combobox/types.js';
|
|
18
|
+
export type * from './icon/types.js';
|
|
19
|
+
export type { SurfaceBaseProps, SurfaceProps, SurfaceRadius } from './surface/types.js';
|
|
20
|
+
export type * from './theme/types.ts';
|
|
21
|
+
export type { CheckboxProps } from './checkbox/types.js';
|
|
22
|
+
export type { SwitchProps } from './switch/types.js';
|
|
23
|
+
export type { ProgressProps } from './progress/types.js';
|
|
24
|
+
export type { SpinnerProps } from './spinner/types.js';
|
|
25
|
+
export type { PopoverProps } from './popover/types.js';
|
|
26
|
+
export type {
|
|
27
|
+
DialogActionProps,
|
|
28
|
+
DialogHeaderDataProps,
|
|
29
|
+
DialogHeaderProps,
|
|
30
|
+
DialogProps
|
|
31
|
+
} from './dialog/types.js';
|
|
32
|
+
export type { TextInputProps } from './text-input/types.js';
|
|
33
|
+
export type { TextAreaProps } from './text-area/types.js';
|
|
34
|
+
export type * from './tree-view/types.js';
|
|
35
|
+
export type { PillDataProps, PillProps } from './pill/types.js';
|
|
36
|
+
export type { PillGroupProps } from './pill-group/types.js';
|
|
37
|
+
export type { PillChoiceGroupProps } from './pill-choice-group/types.js';
|
|
38
|
+
export type {
|
|
39
|
+
OptionProps,
|
|
40
|
+
SelectEmptyProps,
|
|
41
|
+
SelectOptionDataProps,
|
|
42
|
+
SelectListProps,
|
|
43
|
+
SelectProps,
|
|
44
|
+
SelectTriggerProps
|
|
45
|
+
} from './select/types.js';
|
package/README.md
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
# Bref: a Svelte UI Component Library
|
|
2
|
-
|
|
3
|
-
**[Live Demo](https://feuersteiner.github.io/bref/)**
|
|
4
|
-
|
|
5
|
-
Bref is a Svelte UI component library designed to be minimal, flexible, and easy to use. It uses Svelte's built-in scoped CSS for styling, no external CSS frameworks required.
|
|
6
|
-
|
|
7
|
-
## What We Promise
|
|
8
|
-
|
|
9
|
-
- **Pure CSS with scoped styles**: Uses Svelte's native styling system for clean, maintainable components
|
|
10
|
-
- **Base UI components with escape hatches**: Access raw CSS properties when you need full control
|
|
11
|
-
- **Clear naming conventions**: Component names resemble HTML as much as possible to avoid confusion
|
|
12
|
-
- **Section-based components**: For more complex UI needs like navbars, modals, and cards
|
|
13
|
-
- **Marketing site components**: Ready-made components for building landing pages and marketing sites
|
|
14
|
-
- **Theming component**: A simple component to style the entire UI library (colors, padding, spacing, fonts, borders...) to your desires
|
|
15
|
-
- **WIP: CLI tool**: Import components directly into your codebase and customize them at will
|
|
16
|
-
|
|
17
|
-
## Installation
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
npm install bref-ui
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Usage
|
|
24
|
-
|
|
25
|
-
```tsx
|
|
26
|
-
<script lang="ts">
|
|
27
|
-
import { Button } from 'bref-ui';
|
|
28
|
-
</script>
|
|
29
|
-
|
|
30
|
-
<Button onclick={() => console.log('Clicked!')}>Click Me</Button>
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Why Bref?
|
|
34
|
-
|
|
35
|
-
- **Scoped CSS**: Uses Svelte's built-in scoped styling, each component's styles are encapsulated and won't leak or conflict.
|
|
36
|
-
- **Minimal**: Only essential components, nothing extra.
|
|
37
|
-
- **Flexible**: Use as an npm package or copy components directly into your project with our CLI tool (WIP).
|
|
38
|
-
- **Batteries included theming**: Just provide your base colors and we handle the rest (see below).
|
|
39
|
-
|
|
40
|
-
## Theming: Just Bring Your Colors
|
|
41
|
-
|
|
42
|
-
Bref is a **batteries included** theming solution. You don't need to be a color theory expert or spend hours crafting the perfect palette.
|
|
43
|
-
|
|
44
|
-
Simply provide your base theme colors, and Bref automatically generates all the necessary CSS variables with proper contrast ratios, hover states, and luminance variations. No more manually calculating shades, tints, or ensuring accessibility compliance.
|
|
45
|
-
|
|
46
|
-
Bref handles:
|
|
47
|
-
|
|
48
|
-
- **Shade generation**: Automatically creates lighter and darker variants
|
|
49
|
-
- **Contrast calculation**: Ensures text remains readable on all backgrounds
|
|
50
|
-
- **State variations**: Hover, active, and disabled states just work
|
|
51
|
-
- **Dark mode**: Seamlessly adapts your palette for dark themes
|
|
52
|
-
|
|
53
|
-
## Base Components
|
|
54
|
-
|
|
55
|
-
- [x] Icon
|
|
56
|
-
- [x] Button
|
|
57
|
-
- [x] Icon Button
|
|
58
|
-
- [x] Progress / Loading
|
|
59
|
-
- [x] Progress Bar
|
|
60
|
-
- [x] Circular
|
|
61
|
-
- [x] Pulsing Dots
|
|
62
|
-
- [x] Morphing Shapes
|
|
63
|
-
- [x] Textual
|
|
64
|
-
- [x] Tree View
|
|
65
|
-
- [x] Pill
|
|
66
|
-
- [-] Inputs
|
|
67
|
-
- [x] Text Input (single line)
|
|
68
|
-
- [x] Area Text Input
|
|
69
|
-
- [x] Slider (range)
|
|
70
|
-
- [ ] File Input
|
|
71
|
-
- [ ] Image Input
|
|
72
|
-
- [ ] Avatar
|
|
73
|
-
- [ ] Select
|
|
74
|
-
- [ ] Skeleton
|
|
75
|
-
- [ ] Checkbox
|
|
76
|
-
- [ ] Badge
|
|
77
|
-
- [ ] Popover
|
|
78
|
-
- [ ] Radio
|
|
79
|
-
- [ ] Switch
|
|
80
|
-
- [ ] Tooltip
|
|
81
|
-
- [ ] Dialog
|
|
82
|
-
- [ ] Toast
|
|
83
|
-
- [ ] Accordion
|
|
84
|
-
|
|
85
|
-
## Section Components
|
|
86
|
-
|
|
87
|
-
- [ ] Nav
|
|
88
|
-
- [ ] Aside
|
|
89
|
-
- [ ] Header
|
|
90
|
-
- [ ] Footer
|
|
91
|
-
- [ ] Article
|
|
92
|
-
- [ ] Card
|
|
93
|
-
- [ ] Tabs
|
|
94
|
-
- [ ] Table
|
|
95
|
-
- [ ] Form
|
|
96
|
-
|
|
97
|
-
## Marketing Components
|
|
98
|
-
|
|
99
|
-
- [ ] Hero
|
|
100
|
-
- [ ] Features
|
|
101
|
-
- [ ] Pricing
|
|
102
|
-
- [ ] FAQ
|
|
103
|
-
- [ ] Testimonials
|
|
104
|
-
- [ ] CTA
|
|
105
|
-
|
|
106
|
-
> If you need something you don't see here, feel free to open an issue or a PR!
|
|
107
|
-
|
|
108
|
-
## License
|
|
109
|
-
|
|
110
|
-
MIT
|