@grantcodes/ui 2.0.0-beta4 → 2.0.2
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/CHANGELOG.md +125 -0
- package/README.md +6 -8
- package/custom-elements.json +4273 -0
- package/package.json +79 -88
- package/src/components/app-bar/app-bar.component.js +90 -0
- package/src/components/app-bar/app-bar.js +8 -0
- package/src/components/app-bar/app-bar.stories.js +84 -0
- package/src/components/app-bar/app-bar.styles.js +227 -0
- package/src/components/app-bar/app-bar.test.js +174 -0
- package/src/components/app-bar/index.js +3 -0
- package/src/components/avatar/avatar.component.js +78 -0
- package/src/components/avatar/avatar.js +18 -0
- package/src/components/avatar/avatar.stories.js +45 -0
- package/src/components/avatar/avatar.styles.js +42 -0
- package/src/components/avatar/avatar.test.js +85 -0
- package/src/components/avatar/index.js +13 -0
- package/src/components/badge/badge.component.js +36 -0
- package/src/components/badge/badge.js +8 -0
- package/src/components/badge/badge.stories.js +46 -0
- package/src/components/badge/badge.styles.js +94 -0
- package/src/components/badge/badge.test.js +70 -0
- package/src/components/badge/index.js +3 -0
- package/src/components/breadcrumb/breadcrumb.component.js +110 -0
- package/src/components/breadcrumb/breadcrumb.js +12 -0
- package/src/components/breadcrumb/breadcrumb.stories.js +25 -0
- package/src/components/breadcrumb/breadcrumb.styles.js +96 -0
- package/src/components/breadcrumb/breadcrumb.test.js +144 -0
- package/src/components/breadcrumb/index.js +3 -0
- package/src/components/button/button.component.js +64 -0
- package/src/components/button/button.js +6 -0
- package/src/components/button/button.stories.js +78 -0
- package/src/components/button/button.styles.js +97 -0
- package/src/components/button/button.test.js +98 -0
- package/src/components/button/index.js +1 -0
- package/src/components/button-group/button-group.component.js +27 -0
- package/src/components/button-group/button-group.js +6 -0
- package/src/components/button-group/button-group.stories.js +33 -0
- package/src/components/button-group/button-group.styles.js +43 -0
- package/src/components/button-group/button-group.test.js +57 -0
- package/src/components/button-group/index.js +1 -0
- package/src/components/card/card.component.js +17 -0
- package/src/components/card/card.js +6 -0
- package/src/components/card/card.stories.js +36 -0
- package/src/components/card/card.styles.js +128 -0
- package/src/components/card/card.test.js +59 -0
- package/src/components/card/index.js +1 -0
- package/src/components/code-preview/code-preview.component.js +53 -0
- package/src/components/code-preview/code-preview.js +7 -0
- package/src/components/code-preview/code-preview.stories.js +67 -0
- package/src/components/code-preview/code-preview.styles.js +18 -0
- package/src/components/code-preview/code-preview.test.js +118 -0
- package/src/components/code-preview/index.js +1 -0
- package/src/components/container/container.component.js +38 -0
- package/src/components/container/container.js +7 -0
- package/src/components/container/container.stories.js +59 -0
- package/src/components/container/container.styles.js +43 -0
- package/src/components/container/container.test.js +84 -0
- package/src/components/container/index.js +1 -0
- package/src/components/dialog/dialog.component.js +78 -0
- package/src/components/dialog/dialog.js +7 -0
- package/src/components/dialog/dialog.stories.js +43 -0
- package/src/components/dialog/dialog.styles.js +74 -0
- package/src/components/dialog/dialog.test.js +97 -0
- package/src/components/dialog/index.js +1 -0
- package/src/components/dropdown/dropdown.component.js +225 -0
- package/src/components/dropdown/dropdown.js +12 -0
- package/src/components/dropdown/dropdown.stories.js +107 -0
- package/src/components/dropdown/dropdown.styles.js +128 -0
- package/src/components/dropdown/dropdown.test.js +144 -0
- package/src/components/dropdown/index.js +3 -0
- package/src/components/dropzone/dropzone.component.js +141 -0
- package/src/components/dropzone/dropzone.js +6 -0
- package/src/components/dropzone/dropzone.stories.js +41 -0
- package/src/components/dropzone/dropzone.styles.js +64 -0
- package/src/components/dropzone/dropzone.test.js +112 -0
- package/src/components/dropzone/index.js +1 -0
- package/src/components/footer/footer-column.component.js +15 -0
- package/src/components/footer/footer-column.styles.js +51 -0
- package/src/components/footer/footer.component.js +38 -0
- package/src/components/footer/footer.js +9 -0
- package/src/components/footer/footer.stories.js +143 -0
- package/src/components/footer/footer.styles.js +90 -0
- package/src/components/footer/footer.test.js +107 -0
- package/src/components/footer/index.js +2 -0
- package/src/components/form-field/form-field.component.js +173 -0
- package/src/components/form-field/form-field.js +7 -0
- package/src/components/form-field/form-field.stories.js +104 -0
- package/src/components/form-field/form-field.styles.js +47 -0
- package/src/components/form-field/form-field.test.js +118 -0
- package/src/components/form-field/index.js +1 -0
- package/src/components/gallery/gallery-image.component.js +52 -0
- package/src/components/gallery/gallery-image.js +7 -0
- package/src/components/gallery/gallery.component.js +25 -0
- package/src/components/gallery/gallery.js +7 -0
- package/src/components/gallery/gallery.stories.js +60 -0
- package/src/components/gallery/gallery.styles.js +56 -0
- package/src/components/gallery/gallery.test.js +58 -0
- package/src/components/gallery/index.js +2 -0
- package/src/components/icon/icon.component.js +14 -0
- package/src/components/icon/icon.js +7 -0
- package/src/components/icon/icon.stories.js +26 -0
- package/src/components/icon/icon.styles.js +28 -0
- package/src/components/icon/icon.test.js +57 -0
- package/src/components/icon/index.js +1 -0
- package/src/components/loading/index.js +1 -0
- package/src/components/loading/loading.component.js +21 -0
- package/src/components/loading/loading.js +7 -0
- package/src/components/loading/loading.stories.js +25 -0
- package/src/components/loading/loading.styles.js +43 -0
- package/src/components/loading/loading.test.js +57 -0
- package/src/components/notice/index.js +1 -0
- package/src/components/notice/notice.component.js +77 -0
- package/src/components/notice/notice.js +7 -0
- package/src/components/notice/notice.stories.js +122 -0
- package/src/components/notice/notice.styles.js +72 -0
- package/src/components/notice/notice.test.js +146 -0
- package/src/components/pagination/index.js +1 -0
- package/src/components/pagination/pagination.component.js +62 -0
- package/src/components/pagination/pagination.js +7 -0
- package/src/components/pagination/pagination.stories.js +34 -0
- package/src/components/pagination/pagination.styles.js +19 -0
- package/src/components/pagination/pagination.test.js +98 -0
- package/src/components/sidebar/index.js +3 -0
- package/src/components/sidebar/sidebar.component.js +165 -0
- package/src/components/sidebar/sidebar.js +8 -0
- package/src/components/sidebar/sidebar.stories.js +155 -0
- package/src/components/sidebar/sidebar.styles.js +192 -0
- package/src/components/sidebar/sidebar.test.js +196 -0
- package/src/components/tabs/index.js +2 -0
- package/src/components/tabs/internal/tabs-button.component.js +39 -0
- package/src/components/tabs/internal/tabs-button.js +7 -0
- package/src/components/tabs/internal/tabs-item.component.js +39 -0
- package/src/components/tabs/tab.component.js +20 -0
- package/src/components/tabs/tab.js +7 -0
- package/src/components/tabs/tabs.component.js +130 -0
- package/src/components/tabs/tabs.js +7 -0
- package/src/components/tabs/tabs.stories.js +39 -0
- package/src/components/tabs/tabs.styles.js +88 -0
- package/src/components/tabs/tabs.test.js +148 -0
- package/src/components/toast/index.js +3 -0
- package/src/components/toast/toast.component.js +187 -0
- package/src/components/toast/toast.js +9 -0
- package/src/components/toast/toast.stories.js +169 -0
- package/src/components/toast/toast.styles.js +207 -0
- package/src/components/toast/toast.test.js +196 -0
- package/src/components/tooltip/index.js +1 -0
- package/src/components/tooltip/tooltip.component.js +70 -0
- package/src/components/tooltip/tooltip.js +7 -0
- package/src/components/tooltip/tooltip.stories.js +33 -0
- package/src/components/tooltip/tooltip.styles.js +78 -0
- package/src/components/tooltip/tooltip.test.js +150 -0
- package/src/css/all.css +1 -0
- package/src/css/base.css +31 -0
- package/src/css/colors.stories.js +192 -0
- package/src/css/elements/a.css +50 -0
- package/src/css/elements/forms/button.css +15 -0
- package/src/css/elements/forms/input.css +183 -0
- package/src/css/elements/forms/label.css +5 -0
- package/src/css/elements/media/image.css +3 -0
- package/src/css/elements.css +5 -0
- package/src/css/elements.stories.js +108 -0
- package/src/css/helpers.css +16 -0
- package/src/css/themes/grantcodes.css +3 -0
- package/src/css/themes/todomap.css +2 -0
- package/src/css/themes/wireframe.css +2 -0
- package/src/css/tokens.stories.js +183 -0
- package/src/css/typography.css +64 -0
- package/src/css/typography.stories.js +179 -0
- package/src/css/util/functions.css +16 -0
- package/src/css/util/index.css +2 -0
- package/src/css/util/mixins.css +63 -0
- package/src/icons.js +3 -0
- package/src/lib/classnames.js +61 -0
- package/src/lib/generate-id.js +10 -0
- package/src/main.js +17 -0
- package/src/test-utils/assert-helpers.js +150 -0
- package/src/test-utils/events.js +88 -0
- package/src/test-utils/fixture.js +77 -0
- package/src/test-utils/index.js +7 -0
- package/dist/components/avatar/avatar.component.js +0 -3
- package/dist/components/avatar/avatar.js +0 -1
- package/dist/components/avatar/avatar.react.js +0 -1
- package/dist/components/avatar/avatar.scss.js +0 -1
- package/dist/components/avatar/index.js +0 -1
- package/dist/components/button/button.component.js +0 -5
- package/dist/components/button/button.js +0 -1
- package/dist/components/button/button.react.js +0 -1
- package/dist/components/button/button.scss.js +0 -1
- package/dist/components/button/index.js +0 -1
- package/dist/components/button-group/button-group.component.js +0 -5
- package/dist/components/button-group/button-group.js +0 -1
- package/dist/components/button-group/button-group.react.js +0 -1
- package/dist/components/button-group/button-group.scss.js +0 -1
- package/dist/components/button-group/index.js +0 -1
- package/dist/components/card/card.component.js +0 -8
- package/dist/components/card/card.js +0 -1
- package/dist/components/card/card.react.js +0 -1
- package/dist/components/card/card.scss.js +0 -1
- package/dist/components/card/index.js +0 -1
- package/dist/components/code-preview/code-preview.component.js +0 -1
- package/dist/components/code-preview/code-preview.js +0 -1
- package/dist/components/code-preview/code-preview.react.js +0 -1
- package/dist/components/code-preview/code-preview.scss.js +0 -1
- package/dist/components/code-preview/index.js +0 -1
- package/dist/components/container/container.component.js +0 -5
- package/dist/components/container/container.js +0 -1
- package/dist/components/container/container.react.js +0 -1
- package/dist/components/container/container.scss.js +0 -1
- package/dist/components/container/index.js +0 -1
- package/dist/components/dialog/dialog.component.js +0 -23
- package/dist/components/dialog/dialog.js +0 -1
- package/dist/components/dialog/dialog.react.js +0 -1
- package/dist/components/dialog/dialog.scss.js +0 -1
- package/dist/components/dialog/index.js +0 -1
- package/dist/components/dropzone/dropzone.component.js +0 -11
- package/dist/components/dropzone/dropzone.js +0 -1
- package/dist/components/dropzone/dropzone.react.js +0 -1
- package/dist/components/dropzone/dropzone.scss.js +0 -1
- package/dist/components/dropzone/index.js +0 -1
- package/dist/components/form-field/form-field.component.js +0 -22
- package/dist/components/form-field/form-field.js +0 -1
- package/dist/components/form-field/form-field.react.js +0 -1
- package/dist/components/form-field/form-field.scss.js +0 -1
- package/dist/components/form-field/index.js +0 -1
- package/dist/components/gallery/gallery-image.component.js +0 -14
- package/dist/components/gallery/gallery-image.js +0 -1
- package/dist/components/gallery/gallery.component.js +0 -5
- package/dist/components/gallery/gallery.js +0 -1
- package/dist/components/gallery/gallery.react.js +0 -1
- package/dist/components/gallery/gallery.scss.js +0 -1
- package/dist/components/gallery/index.js +0 -1
- package/dist/components/icon/icon.component.js +0 -1
- package/dist/components/icon/icon.js +0 -1
- package/dist/components/icon/icon.react.js +0 -1
- package/dist/components/icon/icon.scss.js +0 -1
- package/dist/components/icon/index.js +0 -1
- package/dist/components/loading/index.js +0 -1
- package/dist/components/loading/loading.component.js +0 -5
- package/dist/components/loading/loading.js +0 -1
- package/dist/components/loading/loading.react.js +0 -1
- package/dist/components/loading/loading.scss.js +0 -1
- package/dist/components/notice/index.js +0 -1
- package/dist/components/notice/notice.component.js +0 -17
- package/dist/components/notice/notice.js +0 -1
- package/dist/components/notice/notice.react.js +0 -1
- package/dist/components/notice/notice.scss.js +0 -1
- package/dist/components/pagination/index.js +0 -1
- package/dist/components/pagination/pagination.component.js +0 -13
- package/dist/components/pagination/pagination.js +0 -1
- package/dist/components/pagination/pagination.react.js +0 -1
- package/dist/components/pagination/pagination.scss.js +0 -1
- package/dist/components/tabs/index.js +0 -1
- package/dist/components/tabs/tab.component.js +0 -1
- package/dist/components/tabs/tab.js +0 -1
- package/dist/components/tabs/tabs-item.component.js +0 -1
- package/dist/components/tabs/tabs-panel.component.js +0 -10
- package/dist/components/tabs/tabs-panel.js +0 -1
- package/dist/components/tabs/tabs-tab.component.js +0 -12
- package/dist/components/tabs/tabs-tab.js +0 -1
- package/dist/components/tabs/tabs.component.js +0 -28
- package/dist/components/tabs/tabs.js +0 -1
- package/dist/components/tabs/tabs.react.js +0 -1
- package/dist/components/tabs/tabs.scss.js +0 -1
- package/dist/components/tooltip/index.js +0 -1
- package/dist/components/tooltip/tooltip.component.js +0 -10
- package/dist/components/tooltip/tooltip.js +0 -1
- package/dist/components/tooltip/tooltip.react.js +0 -1
- package/dist/components/tooltip/tooltip.scss.js +0 -1
- package/dist/css/base.css +0 -1
- package/dist/css/themes/grantcodes.css +0 -1
- package/dist/fonts/greycliff-bold-oblique.woff +0 -0
- package/dist/fonts/greycliff-bold-oblique.woff2 +0 -0
- package/dist/fonts/greycliff-bold.woff +0 -0
- package/dist/fonts/greycliff-bold.woff2 +0 -0
- package/dist/fonts/greycliff-demi-bold-oblique.woff +0 -0
- package/dist/fonts/greycliff-demi-bold-oblique.woff2 +0 -0
- package/dist/fonts/greycliff-demi-bold.woff +0 -0
- package/dist/fonts/greycliff-demi-bold.woff2 +0 -0
- package/dist/fonts/greycliff-extra-bold-oblique.woff +0 -0
- package/dist/fonts/greycliff-extra-bold-oblique.woff2 +0 -0
- package/dist/fonts/greycliff-extra-bold.woff +0 -0
- package/dist/fonts/greycliff-extra-bold.woff2 +0 -0
- package/dist/fonts/greycliff-extra-light-oblique.woff +0 -0
- package/dist/fonts/greycliff-extra-light-oblique.woff2 +0 -0
- package/dist/fonts/greycliff-extra-light.woff +0 -0
- package/dist/fonts/greycliff-extra-light.woff2 +0 -0
- package/dist/fonts/greycliff-heavy-oblique.woff +0 -0
- package/dist/fonts/greycliff-heavy-oblique.woff2 +0 -0
- package/dist/fonts/greycliff-heavy.woff +0 -0
- package/dist/fonts/greycliff-heavy.woff2 +0 -0
- package/dist/fonts/greycliff-light-oblique.woff +0 -0
- package/dist/fonts/greycliff-light-oblique.woff2 +0 -0
- package/dist/fonts/greycliff-light.woff +0 -0
- package/dist/fonts/greycliff-light.woff2 +0 -0
- package/dist/fonts/greycliff-medium-oblique.woff +0 -0
- package/dist/fonts/greycliff-medium-oblique.woff2 +0 -0
- package/dist/fonts/greycliff-medium.woff +0 -0
- package/dist/fonts/greycliff-medium.woff2 +0 -0
- package/dist/fonts/greycliff-regular-oblique.woff +0 -0
- package/dist/fonts/greycliff-regular-oblique.woff2 +0 -0
- package/dist/fonts/greycliff-regular.woff +0 -0
- package/dist/fonts/greycliff-regular.woff2 +0 -0
- package/dist/fonts/greycliff-thin-oblique.woff +0 -0
- package/dist/fonts/greycliff-thin-oblique.woff2 +0 -0
- package/dist/fonts/greycliff-thin.woff +0 -0
- package/dist/fonts/greycliff-thin.woff2 +0 -0
- package/dist/icons.js +0 -1
- package/dist/lib/generate-id.js +0 -1
- package/dist/main.js +0 -1
- package/dist/react.js +0 -1
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { css } from "lit";
|
|
2
|
+
|
|
3
|
+
export const buttonStyles = css`
|
|
4
|
+
/* Inlined component-base mixin */
|
|
5
|
+
*,
|
|
6
|
+
*::before,
|
|
7
|
+
*::after {
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
:host {
|
|
12
|
+
display: block;
|
|
13
|
+
--button-border-radius-start: var(--g-theme-border-radius-md);
|
|
14
|
+
--button-border-radius-end: var(--g-theme-border-radius-md);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.button {
|
|
18
|
+
display: inline-flex;
|
|
19
|
+
flex-direction: row;
|
|
20
|
+
align-items: center;
|
|
21
|
+
gap: 0.5rem;
|
|
22
|
+
background: var(--g-theme-button-primary-color-background-default);
|
|
23
|
+
color: var(--g-theme-button-primary-color-content-default);
|
|
24
|
+
border-width: var(--g-theme-border-width-md);
|
|
25
|
+
border-style: solid;
|
|
26
|
+
border-color: var(--g-theme-button-primary-color-border-default);
|
|
27
|
+
padding: 0.5em 1em;
|
|
28
|
+
border-start-start-radius: var(--button-border-radius-start);
|
|
29
|
+
border-start-end-radius: var(--button-border-radius-end);
|
|
30
|
+
border-end-start-radius: var(--button-border-radius-start);
|
|
31
|
+
border-end-end-radius: var(--button-border-radius-end);
|
|
32
|
+
font-size: 1rem;
|
|
33
|
+
font-weight: bold;
|
|
34
|
+
letter-spacing: 0.05em;
|
|
35
|
+
text-decoration: none;
|
|
36
|
+
outline: 1px solid transparent;
|
|
37
|
+
transition:
|
|
38
|
+
color 0.2s,
|
|
39
|
+
border-color 0.2s,
|
|
40
|
+
background-color 0.2s,
|
|
41
|
+
outline 0.2s;
|
|
42
|
+
|
|
43
|
+
/* Inlined focus-ring styles */
|
|
44
|
+
outline-color: transparent;
|
|
45
|
+
outline-offset: var(--g-theme-focus-ring-offset-default);
|
|
46
|
+
outline-style: solid;
|
|
47
|
+
outline-width: var(--g-theme-focus-ring-width-default);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.button:focus-visible {
|
|
51
|
+
outline-color: var(--g-theme-focus-ring-color-default);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@media (prefers-contrast: more) {
|
|
55
|
+
.button:focus-visible {
|
|
56
|
+
outline-color: var(--g-theme-focus-ring-color-contrast);
|
|
57
|
+
box-shadow: 0 0 0
|
|
58
|
+
calc(
|
|
59
|
+
(
|
|
60
|
+
var(--g-theme-focus-ring-width-default) +
|
|
61
|
+
var(--g-theme-focus-ring-offset-default)
|
|
62
|
+
) *
|
|
63
|
+
1.5
|
|
64
|
+
)
|
|
65
|
+
var(--g-theme-focus-ring-color-contrast-shadow);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.button:hover,
|
|
70
|
+
.button:focus-visible {
|
|
71
|
+
color: var(--g-theme-button-primary-color-content-hover);
|
|
72
|
+
background: var(--g-theme-button-primary-color-background-hover);
|
|
73
|
+
border-color: var(--g-theme-button-primary-color-border-hover);
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
text-decoration: none;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.button:active {
|
|
79
|
+
color: var(--g-theme-button-primary-color-content-active);
|
|
80
|
+
background: var(--g-theme-button-primary-color-background-active);
|
|
81
|
+
border-color: var(--g-theme-button-primary-color-border-active);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.button:active {
|
|
85
|
+
transform: translateY(1px);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.button[disabled] {
|
|
89
|
+
background: var(--g-theme-button-primary-color-background-disabled);
|
|
90
|
+
color: var(--g-theme-button-primary-color-content-disabled);
|
|
91
|
+
border-color: var(--g-theme-button-primary-color-border-disabled);
|
|
92
|
+
cursor: not-allowed;
|
|
93
|
+
filter: grayscale(70%);
|
|
94
|
+
opacity: 0.8;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
`;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { describe, it, afterEach } from "node:test";
|
|
2
|
+
import { strict as assert } from "node:assert";
|
|
3
|
+
import { fixture, cleanup, click } from "../../test-utils/index.js";
|
|
4
|
+
import "./button.js";
|
|
5
|
+
|
|
6
|
+
describe("Button Component", () => {
|
|
7
|
+
let element;
|
|
8
|
+
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
cleanup(element);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("should render with default properties", async () => {
|
|
14
|
+
element = await fixture("grantcodes-button");
|
|
15
|
+
assert.ok(element, "Element should be created");
|
|
16
|
+
assert.ok(element.shadowRoot, "Element should have shadow root");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("should render button element by default", async () => {
|
|
20
|
+
element = await fixture("grantcodes-button");
|
|
21
|
+
const button = element.shadowRoot.querySelector("button");
|
|
22
|
+
assert.ok(button, "Button element should exist");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("should render link when href is provided", async () => {
|
|
26
|
+
element = await fixture("grantcodes-button", {
|
|
27
|
+
href: "https://example.com",
|
|
28
|
+
});
|
|
29
|
+
await element.updateComplete;
|
|
30
|
+
|
|
31
|
+
const link = element.shadowRoot.querySelector("a");
|
|
32
|
+
assert.ok(link, "Link element should exist");
|
|
33
|
+
const href = link.getAttribute("href");
|
|
34
|
+
assert.ok(href, "Link should have href attribute");
|
|
35
|
+
assert.ok(href.includes("example.com") || href === "https://example.com", "Link href should contain example.com");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("should be disabled when disabled property is set", async () => {
|
|
39
|
+
element = await fixture("grantcodes-button", {
|
|
40
|
+
disabled: true,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const button = element.shadowRoot.querySelector("button");
|
|
44
|
+
assert.ok(button.disabled, "Button should be disabled");
|
|
45
|
+
assert.ok(button.hasAttribute("disabled"), "Button should have disabled attribute");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("should emit click event when clicked", async () => {
|
|
49
|
+
element = await fixture("grantcodes-button");
|
|
50
|
+
const button = element.shadowRoot.querySelector("button");
|
|
51
|
+
|
|
52
|
+
let clicked = false;
|
|
53
|
+
element.addEventListener("click", () => {
|
|
54
|
+
clicked = true;
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
click(button);
|
|
58
|
+
assert.ok(clicked, "Click event should have fired");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("should not emit click event when disabled", async () => {
|
|
62
|
+
element = await fixture("grantcodes-button", {
|
|
63
|
+
disabled: true,
|
|
64
|
+
});
|
|
65
|
+
const button = element.shadowRoot.querySelector("button");
|
|
66
|
+
|
|
67
|
+
let clicked = false;
|
|
68
|
+
element.addEventListener("click", () => {
|
|
69
|
+
clicked = true;
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
click(button);
|
|
73
|
+
assert.ok(!clicked, "Click event should not fire when disabled");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("should support different button types", async () => {
|
|
77
|
+
const types = ["button", "submit", "reset"];
|
|
78
|
+
|
|
79
|
+
for (const type of types) {
|
|
80
|
+
const testElement = await fixture("grantcodes-button", { type });
|
|
81
|
+
const button = testElement.shadowRoot.querySelector("button");
|
|
82
|
+
assert.strictEqual(button.type, type, `Button type should be ${type}`);
|
|
83
|
+
cleanup(testElement);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("should render slotted content", async () => {
|
|
88
|
+
element = await fixture("grantcodes-button");
|
|
89
|
+
element.textContent = "Click me";
|
|
90
|
+
|
|
91
|
+
await element.updateComplete;
|
|
92
|
+
|
|
93
|
+
const slot = element.shadowRoot.querySelector("slot");
|
|
94
|
+
assert.ok(slot, "Slot should exist");
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./button";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { LitElement } from "lit";
|
|
2
|
+
import { html } from "lit/static-html.js";
|
|
3
|
+
import { buttonGroupStyles } from "./button-group.styles.js";
|
|
4
|
+
|
|
5
|
+
export class GrantCodesButtonGroup extends LitElement {
|
|
6
|
+
// Styles are scoped to this element: they won't conflict with styles
|
|
7
|
+
// on the main page or in other components. Styling API can be exposed
|
|
8
|
+
// via CSS custom properties.
|
|
9
|
+
static styles = [buttonGroupStyles];
|
|
10
|
+
|
|
11
|
+
// Define reactive properties--updating a reactive property causes
|
|
12
|
+
// the component to update.
|
|
13
|
+
// @property() label = 'Button Label'
|
|
14
|
+
|
|
15
|
+
// The render() method is called any time reactive properties change.
|
|
16
|
+
// Return HTML in a string template literal tagged with the `html`
|
|
17
|
+
// tag function to describe the component's internal DOM.
|
|
18
|
+
// Expressions can set attribute values, property values, event handlers,
|
|
19
|
+
// and child nodes/text.
|
|
20
|
+
render() {
|
|
21
|
+
return html`
|
|
22
|
+
<div class="button-group">
|
|
23
|
+
<slot></slot>
|
|
24
|
+
</div>
|
|
25
|
+
`;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { getStorybookHelpers } from "@wc-toolkit/storybook-helpers";
|
|
2
|
+
const { events, args, argTypes, template } = getStorybookHelpers(
|
|
3
|
+
"grantcodes-button-group",
|
|
4
|
+
);
|
|
5
|
+
import { html } from "lit/static-html.js";
|
|
6
|
+
import "./button-group";
|
|
7
|
+
import "../button/button";
|
|
8
|
+
|
|
9
|
+
const meta = {
|
|
10
|
+
title: "Components/ButtonGroup",
|
|
11
|
+
component: "grantcodes-button-group",
|
|
12
|
+
args: {
|
|
13
|
+
...args,
|
|
14
|
+
},
|
|
15
|
+
argTypes,
|
|
16
|
+
render: (args) =>
|
|
17
|
+
template(
|
|
18
|
+
args,
|
|
19
|
+
html`
|
|
20
|
+
<grantcodes-button>Button 1</grantcodes-button>
|
|
21
|
+
<grantcodes-button>Button 2</grantcodes-button>
|
|
22
|
+
<grantcodes-button>Button 3</grantcodes-button>`,
|
|
23
|
+
),
|
|
24
|
+
parameters: {
|
|
25
|
+
actions: {
|
|
26
|
+
handles: events,
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default meta;
|
|
32
|
+
|
|
33
|
+
export const ButtonGroup = {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { css } from "lit";
|
|
2
|
+
|
|
3
|
+
export const buttonGroupStyles = css`
|
|
4
|
+
/* Inlined component-base mixin */
|
|
5
|
+
*,
|
|
6
|
+
*::before,
|
|
7
|
+
*::after {
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
:host {
|
|
12
|
+
display: block;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.button-group {
|
|
16
|
+
display: inline-flex;
|
|
17
|
+
flex-direction: row;
|
|
18
|
+
flex-wrap: wrap;
|
|
19
|
+
background: var(--g-theme-color-background-default);
|
|
20
|
+
border-radius: var(--g-theme-border-radius-md);
|
|
21
|
+
min-width: fit-content;
|
|
22
|
+
max-width: 100%;
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.button-group ::slotted(grantcodes-button) {
|
|
27
|
+
--button-border-radius-start: 0;
|
|
28
|
+
--button-border-radius-end: 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.button-group ::slotted(grantcodes-button:first-child) {
|
|
32
|
+
--button-border-radius-start: var(--g-theme-border-radius-md);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.button-group ::slotted(grantcodes-button:last-child) {
|
|
36
|
+
--button-border-radius-end: var(--g-theme-border-radius-md);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.button-group ::slotted(grantcodes-button:focus-visible) {
|
|
40
|
+
position: relative;
|
|
41
|
+
z-index: 1;
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { describe, it, afterEach } from "node:test";
|
|
2
|
+
import { strict as assert } from "node:assert";
|
|
3
|
+
import { fixture, cleanup } from "../../test-utils/index.js";
|
|
4
|
+
import "./button-group.js";
|
|
5
|
+
|
|
6
|
+
describe("Button Group Component", () => {
|
|
7
|
+
let element;
|
|
8
|
+
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
cleanup(element);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("should render with default properties", async () => {
|
|
14
|
+
element = await fixture("grantcodes-button-group");
|
|
15
|
+
assert.ok(element, "Element should be created");
|
|
16
|
+
assert.ok(element.shadowRoot, "Element should have shadow root");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("should render button group wrapper", async () => {
|
|
20
|
+
element = await fixture("grantcodes-button-group");
|
|
21
|
+
const group = element.shadowRoot.querySelector(".button-group");
|
|
22
|
+
assert.ok(group, "Button group wrapper should exist");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("should have slot for buttons", async () => {
|
|
26
|
+
element = await fixture("grantcodes-button-group");
|
|
27
|
+
const slot = element.shadowRoot.querySelector("slot");
|
|
28
|
+
assert.ok(slot, "Slot should exist for buttons");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("should support multiple slotted buttons", async () => {
|
|
32
|
+
element = await fixture("grantcodes-button-group");
|
|
33
|
+
|
|
34
|
+
const button1 = document.createElement("button");
|
|
35
|
+
button1.textContent = "Button 1";
|
|
36
|
+
const button2 = document.createElement("button");
|
|
37
|
+
button2.textContent = "Button 2";
|
|
38
|
+
const button3 = document.createElement("button");
|
|
39
|
+
button3.textContent = "Button 3";
|
|
40
|
+
|
|
41
|
+
element.appendChild(button1);
|
|
42
|
+
element.appendChild(button2);
|
|
43
|
+
element.appendChild(button3);
|
|
44
|
+
|
|
45
|
+
await element.updateComplete;
|
|
46
|
+
|
|
47
|
+
assert.strictEqual(element.children.length, 3, "Should have three buttons");
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("should group buttons together visually", async () => {
|
|
51
|
+
element = await fixture("grantcodes-button-group");
|
|
52
|
+
const group = element.shadowRoot.querySelector(".button-group");
|
|
53
|
+
assert.ok(group, "Button group should provide visual grouping");
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./button-group";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { LitElement } from "lit";
|
|
2
|
+
import { html } from "lit/static-html.js";
|
|
3
|
+
import { cardStyles } from "./card.styles.js";
|
|
4
|
+
|
|
5
|
+
export class GrantCodesCard extends LitElement {
|
|
6
|
+
static styles = [cardStyles];
|
|
7
|
+
|
|
8
|
+
render() {
|
|
9
|
+
return html`
|
|
10
|
+
<div class="card">
|
|
11
|
+
<div class="card__header"><slot name="header"></slot></div>
|
|
12
|
+
<div class="card__content"><slot></slot></div>
|
|
13
|
+
<div class="card__footer"><slot name="footer"></slot></div>
|
|
14
|
+
</div>
|
|
15
|
+
`;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { html } from "lit/static-html.js";
|
|
2
|
+
import { getStorybookHelpers } from "@wc-toolkit/storybook-helpers";
|
|
3
|
+
const { events, args, argTypes, template } =
|
|
4
|
+
getStorybookHelpers("grantcodes-card");
|
|
5
|
+
import "./card.js";
|
|
6
|
+
import "../button-group/button-group.js";
|
|
7
|
+
import "../button/button.js";
|
|
8
|
+
|
|
9
|
+
const meta = {
|
|
10
|
+
title: "Components/Card",
|
|
11
|
+
component: "grantcodes-card",
|
|
12
|
+
args: {
|
|
13
|
+
...args,
|
|
14
|
+
content: "Here is the card content",
|
|
15
|
+
},
|
|
16
|
+
argTypes,
|
|
17
|
+
render: (args) =>
|
|
18
|
+
template(
|
|
19
|
+
args,
|
|
20
|
+
html`<h3 slot="header">Card Header</h3>
|
|
21
|
+
<p>${args.content}</p>
|
|
22
|
+
<grantcodes-button-group slot="footer">
|
|
23
|
+
<grantcodes-button>Action 1</grantcodes-button>
|
|
24
|
+
<grantcodes-button>Action 2</grantcodes-button>
|
|
25
|
+
</grantcodes-button-group>`,
|
|
26
|
+
),
|
|
27
|
+
parameters: {
|
|
28
|
+
actions: {
|
|
29
|
+
handles: events,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default meta;
|
|
35
|
+
|
|
36
|
+
export const Card = {};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { css } from "lit";
|
|
2
|
+
|
|
3
|
+
export const cardStyles = css`
|
|
4
|
+
/* Inlined component-base mixin */
|
|
5
|
+
*,
|
|
6
|
+
*::before,
|
|
7
|
+
*::after {
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
:host {
|
|
12
|
+
display: block;
|
|
13
|
+
/* Enable container queries for responsive card layouts */
|
|
14
|
+
container-type: inline-size;
|
|
15
|
+
container-name: card;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.card {
|
|
19
|
+
display: flex;
|
|
20
|
+
inline-size: 100%;
|
|
21
|
+
flex-direction: column;
|
|
22
|
+
justify-content: flex-start;
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
background: var(--g-theme-color-background-default);
|
|
25
|
+
border-style: solid;
|
|
26
|
+
border-width: var(--g-theme-border-width-sm);
|
|
27
|
+
border-color: var(--g-theme-color-border-default);
|
|
28
|
+
border-radius: var(--g-theme-border-radius-md);
|
|
29
|
+
box-shadow:
|
|
30
|
+
0 1px 3px rgba(0, 0, 0, 0.12),
|
|
31
|
+
0 1px 2px rgba(0, 0, 0, 0.24);
|
|
32
|
+
transition:
|
|
33
|
+
box-shadow 0.2s ease,
|
|
34
|
+
transform 0.2s ease,
|
|
35
|
+
border-color 0.2s ease,
|
|
36
|
+
background-color 0.2s ease;
|
|
37
|
+
box-shadow:
|
|
38
|
+
0 8px 24px rgba(0, 0, 0, 0.08),
|
|
39
|
+
0 6px 12px rgba(0, 0, 0, 0.04);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* Image support - images in header or content will be styled appropriately */
|
|
43
|
+
.card__header img,
|
|
44
|
+
.card__content img {
|
|
45
|
+
display: block;
|
|
46
|
+
width: 100%;
|
|
47
|
+
height: auto;
|
|
48
|
+
border-radius: inherit;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.card__header {
|
|
52
|
+
padding-inline: 1rem;
|
|
53
|
+
padding-block: calc(1rem * 0.75);
|
|
54
|
+
border-block-end: 1px solid var(--g-theme-color-border-default);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.card__header ::slotted(*) {
|
|
58
|
+
margin: 0;
|
|
59
|
+
font-weight: 600;
|
|
60
|
+
font-size: var(--g-typography-font-size-24);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.card__content {
|
|
64
|
+
display: flex;
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
justify-content: flex-start;
|
|
67
|
+
gap: 1rem;
|
|
68
|
+
padding-block: 1rem;
|
|
69
|
+
padding-inline: 1rem;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.card__content > * {
|
|
73
|
+
margin: 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.card__footer {
|
|
77
|
+
display: flex;
|
|
78
|
+
flex-direction: row;
|
|
79
|
+
flex-wrap: wrap;
|
|
80
|
+
justify-content: flex-end;
|
|
81
|
+
gap: calc(1rem * 0.5);
|
|
82
|
+
border-block-start: 1px solid var(--g-theme-color-border-default);
|
|
83
|
+
background: var(--g-theme-color-background-default);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.card__footer ::slotted(grantcodes-button-group) {
|
|
87
|
+
width: 100%;
|
|
88
|
+
justify-content: flex-end;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.card__meta {
|
|
92
|
+
display: flex;
|
|
93
|
+
flex-direction: row;
|
|
94
|
+
align-items: center;
|
|
95
|
+
flex-wrap: wrap;
|
|
96
|
+
gap: 1rem;
|
|
97
|
+
margin: 0;
|
|
98
|
+
padding-inline: 1rem;
|
|
99
|
+
padding-block: 1em;
|
|
100
|
+
font-size: var(--g-typography-font-size-14);
|
|
101
|
+
/* Use color-mix() for modern color manipulation */
|
|
102
|
+
background-color: color-mix(
|
|
103
|
+
in srgb,
|
|
104
|
+
var(--g-theme-color-background-default) 90%,
|
|
105
|
+
var(--g-color-brand-purple-500) 10%
|
|
106
|
+
);
|
|
107
|
+
color: var(--g-theme-color-content-default);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.card__meta__item {
|
|
111
|
+
display: flex;
|
|
112
|
+
flex-direction: row;
|
|
113
|
+
align-items: center;
|
|
114
|
+
flex-wrap: nowrap;
|
|
115
|
+
gap: 0.3em;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.card__meta__item dt,
|
|
119
|
+
.card__meta__item dd {
|
|
120
|
+
display: block;
|
|
121
|
+
margin: 0;
|
|
122
|
+
padding: 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.card__meta__item dt::after {
|
|
126
|
+
content: ":";
|
|
127
|
+
}
|
|
128
|
+
`;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, it, afterEach } from "node:test";
|
|
2
|
+
import { strict as assert } from "node:assert";
|
|
3
|
+
import { fixture, cleanup } from "../../test-utils/index.js";
|
|
4
|
+
import "./card.js";
|
|
5
|
+
|
|
6
|
+
describe("Card Component", () => {
|
|
7
|
+
let element;
|
|
8
|
+
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
cleanup(element);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("should render with default properties", async () => {
|
|
14
|
+
element = await fixture("grantcodes-card");
|
|
15
|
+
assert.ok(element, "Element should be created");
|
|
16
|
+
assert.ok(element.shadowRoot, "Element should have shadow root");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("should have default slot", async () => {
|
|
20
|
+
element = await fixture("grantcodes-card");
|
|
21
|
+
const slot = element.shadowRoot.querySelector("slot:not([name])");
|
|
22
|
+
assert.ok(slot, "Default slot should exist");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("should have header slot", async () => {
|
|
26
|
+
element = await fixture("grantcodes-card");
|
|
27
|
+
const headerSlot = element.shadowRoot.querySelector('slot[name="header"]');
|
|
28
|
+
assert.ok(headerSlot, "Header slot should exist");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("should have footer slot", async () => {
|
|
32
|
+
element = await fixture("grantcodes-card");
|
|
33
|
+
const footerSlot = element.shadowRoot.querySelector('slot[name="footer"]');
|
|
34
|
+
assert.ok(footerSlot, "Footer slot should exist");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("should render card wrapper", async () => {
|
|
38
|
+
element = await fixture("grantcodes-card");
|
|
39
|
+
const card = element.shadowRoot.querySelector(".card");
|
|
40
|
+
assert.ok(card, "Card wrapper should exist");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should support slotted content", async () => {
|
|
44
|
+
element = await fixture("grantcodes-card");
|
|
45
|
+
const content = document.createElement("p");
|
|
46
|
+
content.textContent = "Card content";
|
|
47
|
+
element.appendChild(content);
|
|
48
|
+
|
|
49
|
+
await element.updateComplete;
|
|
50
|
+
|
|
51
|
+
assert.strictEqual(
|
|
52
|
+
element.querySelector("p").textContent,
|
|
53
|
+
"Card content",
|
|
54
|
+
"Slotted content should be present",
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./card";
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { LitElement } from "lit";
|
|
2
|
+
import { html } from "lit/static-html.js";
|
|
3
|
+
import { codePreviewStyles } from "./code-preview.styles.js";
|
|
4
|
+
|
|
5
|
+
export class GrantCodesCodePreview extends LitElement {
|
|
6
|
+
static styles = [codePreviewStyles];
|
|
7
|
+
|
|
8
|
+
static properties = {
|
|
9
|
+
language: { type: String },
|
|
10
|
+
theme: { type: String },
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
constructor() {
|
|
14
|
+
super();
|
|
15
|
+
|
|
16
|
+
this.language = "html";
|
|
17
|
+
this.theme = "aurora-x";
|
|
18
|
+
this.codePreview = null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async doHighlight() {
|
|
22
|
+
const rawCode = this.textContent ?? "";
|
|
23
|
+
const { codeToHtml } = await import("shiki/bundle/web");
|
|
24
|
+
const highlightedCode = await codeToHtml(rawCode.trim(), {
|
|
25
|
+
lang: this.language,
|
|
26
|
+
theme: this.theme,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
this.codePreview.innerHTML = highlightedCode;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async firstUpdated() {
|
|
33
|
+
this.codePreview = this.renderRoot.querySelector(".code-preview");
|
|
34
|
+
// Only highlight if we have content and we're in a browser environment,
|
|
35
|
+
// and not in a unit test environment
|
|
36
|
+
const isTestEnv =
|
|
37
|
+
typeof process !== "undefined" && process?.env?.NODE_ENV === "test";
|
|
38
|
+
if (this.textContent && typeof window !== "undefined" && !isTestEnv) {
|
|
39
|
+
try {
|
|
40
|
+
await this.doHighlight();
|
|
41
|
+
} catch (error) {
|
|
42
|
+
// Silently fail in test environments
|
|
43
|
+
console.warn("Code highlighting failed:", error);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
render() {
|
|
49
|
+
return html`<div class="code-preview">
|
|
50
|
+
<pre><slot></slot></pre>
|
|
51
|
+
</div> `;
|
|
52
|
+
}
|
|
53
|
+
}
|