@dsn-starter-kit/components-web 1.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/README.md +120 -0
- package/dist/button/Button.d.ts +50 -0
- package/dist/button/Button.d.ts.map +1 -0
- package/dist/button/Button.js +247 -0
- package/dist/button/Button.js.map +1 -0
- package/dist/button/Button.test.d.ts +2 -0
- package/dist/button/Button.test.d.ts.map +1 -0
- package/dist/button/Button.test.js +299 -0
- package/dist/button/Button.test.js.map +1 -0
- package/dist/button/button-styles.generated.d.ts +2 -0
- package/dist/button/button-styles.generated.d.ts.map +1 -0
- package/dist/button/button-styles.generated.js +4 -0
- package/dist/button/button-styles.generated.js.map +1 -0
- package/dist/button/index.d.ts +3 -0
- package/dist/button/index.d.ts.map +1 -0
- package/dist/button/index.js +2 -0
- package/dist/button/index.js.map +1 -0
- package/dist/heading/Heading.d.ts +30 -0
- package/dist/heading/Heading.d.ts.map +1 -0
- package/dist/heading/Heading.js +79 -0
- package/dist/heading/Heading.js.map +1 -0
- package/dist/heading/Heading.test.d.ts +2 -0
- package/dist/heading/Heading.test.d.ts.map +1 -0
- package/dist/heading/Heading.test.js +157 -0
- package/dist/heading/Heading.test.js.map +1 -0
- package/dist/heading/heading-styles.generated.d.ts +2 -0
- package/dist/heading/heading-styles.generated.d.ts.map +1 -0
- package/dist/heading/heading-styles.generated.js +4 -0
- package/dist/heading/heading-styles.generated.js.map +1 -0
- package/dist/heading/index.d.ts +3 -0
- package/dist/heading/index.d.ts.map +1 -0
- package/dist/heading/index.js +2 -0
- package/dist/heading/index.js.map +1 -0
- package/dist/icon/Icon.d.ts +31 -0
- package/dist/icon/Icon.d.ts.map +1 -0
- package/dist/icon/Icon.js +110 -0
- package/dist/icon/Icon.js.map +1 -0
- package/dist/icon/Icon.test.d.ts +2 -0
- package/dist/icon/Icon.test.d.ts.map +1 -0
- package/dist/icon/Icon.test.js +193 -0
- package/dist/icon/Icon.test.js.map +1 -0
- package/dist/icon/icon-paths.generated.d.ts +2 -0
- package/dist/icon/icon-paths.generated.d.ts.map +1 -0
- package/dist/icon/icon-paths.generated.js +56 -0
- package/dist/icon/icon-paths.generated.js.map +1 -0
- package/dist/icon/icon-styles.generated.d.ts +2 -0
- package/dist/icon/icon-styles.generated.d.ts.map +1 -0
- package/dist/icon/icon-styles.generated.js +4 -0
- package/dist/icon/icon-styles.generated.js.map +1 -0
- package/dist/icon/index.d.ts +3 -0
- package/dist/icon/index.d.ts.map +1 -0
- package/dist/icon/index.js +2 -0
- package/dist/icon/index.js.map +1 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +71 -0
- package/dist/index.js.map +1 -0
- package/dist/link/Link.d.ts +52 -0
- package/dist/link/Link.d.ts.map +1 -0
- package/dist/link/Link.js +260 -0
- package/dist/link/Link.js.map +1 -0
- package/dist/link/Link.test.d.ts +2 -0
- package/dist/link/Link.test.d.ts.map +1 -0
- package/dist/link/Link.test.js +256 -0
- package/dist/link/Link.test.js.map +1 -0
- package/dist/link/index.d.ts +3 -0
- package/dist/link/index.d.ts.map +1 -0
- package/dist/link/index.js +2 -0
- package/dist/link/index.js.map +1 -0
- package/dist/link/link-styles.generated.d.ts +2 -0
- package/dist/link/link-styles.generated.d.ts.map +1 -0
- package/dist/link/link-styles.generated.js +4 -0
- package/dist/link/link-styles.generated.js.map +1 -0
- package/dist/ordered-list/OrderedList.d.ts +32 -0
- package/dist/ordered-list/OrderedList.d.ts.map +1 -0
- package/dist/ordered-list/OrderedList.js +72 -0
- package/dist/ordered-list/OrderedList.js.map +1 -0
- package/dist/ordered-list/OrderedList.test.d.ts +2 -0
- package/dist/ordered-list/OrderedList.test.d.ts.map +1 -0
- package/dist/ordered-list/OrderedList.test.js +82 -0
- package/dist/ordered-list/OrderedList.test.js.map +1 -0
- package/dist/ordered-list/index.d.ts +2 -0
- package/dist/ordered-list/index.d.ts.map +1 -0
- package/dist/ordered-list/index.js +2 -0
- package/dist/ordered-list/index.js.map +1 -0
- package/dist/ordered-list/ordered-list-styles.generated.d.ts +2 -0
- package/dist/ordered-list/ordered-list-styles.generated.d.ts.map +1 -0
- package/dist/ordered-list/ordered-list-styles.generated.js +4 -0
- package/dist/ordered-list/ordered-list-styles.generated.js.map +1 -0
- package/dist/paragraph/Paragraph.d.ts +26 -0
- package/dist/paragraph/Paragraph.d.ts.map +1 -0
- package/dist/paragraph/Paragraph.js +60 -0
- package/dist/paragraph/Paragraph.js.map +1 -0
- package/dist/paragraph/Paragraph.test.d.ts +2 -0
- package/dist/paragraph/Paragraph.test.d.ts.map +1 -0
- package/dist/paragraph/Paragraph.test.js +121 -0
- package/dist/paragraph/Paragraph.test.js.map +1 -0
- package/dist/paragraph/index.d.ts +3 -0
- package/dist/paragraph/index.d.ts.map +1 -0
- package/dist/paragraph/index.js +2 -0
- package/dist/paragraph/index.js.map +1 -0
- package/dist/paragraph/paragraph-styles.generated.d.ts +2 -0
- package/dist/paragraph/paragraph-styles.generated.d.ts.map +1 -0
- package/dist/paragraph/paragraph-styles.generated.js +4 -0
- package/dist/paragraph/paragraph-styles.generated.js.map +1 -0
- package/dist/unordered-list/UnorderedList.d.ts +22 -0
- package/dist/unordered-list/UnorderedList.d.ts.map +1 -0
- package/dist/unordered-list/UnorderedList.js +42 -0
- package/dist/unordered-list/UnorderedList.js.map +1 -0
- package/dist/unordered-list/UnorderedList.test.d.ts +2 -0
- package/dist/unordered-list/UnorderedList.test.d.ts.map +1 -0
- package/dist/unordered-list/UnorderedList.test.js +56 -0
- package/dist/unordered-list/UnorderedList.test.js.map +1 -0
- package/dist/unordered-list/index.d.ts +2 -0
- package/dist/unordered-list/index.d.ts.map +1 -0
- package/dist/unordered-list/index.js +2 -0
- package/dist/unordered-list/index.js.map +1 -0
- package/dist/unordered-list/unordered-list-styles.generated.d.ts +2 -0
- package/dist/unordered-list/unordered-list-styles.generated.d.ts.map +1 -0
- package/dist/unordered-list/unordered-list-styles.generated.js +4 -0
- package/dist/unordered-list/unordered-list-styles.generated.js.map +1 -0
- package/package.json +42 -0
- package/src/button/Button.test.ts +360 -0
- package/src/button/Button.ts +299 -0
- package/src/button/button-demo.html +477 -0
- package/src/button/button-styles.generated.ts +3 -0
- package/src/button/button.shadow.css +20 -0
- package/src/button/index.ts +2 -0
- package/src/heading/Heading.test.ts +186 -0
- package/src/heading/Heading.ts +104 -0
- package/src/heading/heading-styles.generated.ts +3 -0
- package/src/heading/heading.shadow.css +11 -0
- package/src/heading/index.ts +2 -0
- package/src/icon/Icon.test.ts +228 -0
- package/src/icon/Icon.ts +136 -0
- package/src/icon/icon-paths.generated.ts +55 -0
- package/src/icon/icon-styles.generated.ts +3 -0
- package/src/icon/icon.shadow.css +13 -0
- package/src/icon/index.ts +2 -0
- package/src/index.ts +83 -0
- package/src/link/Link.test.ts +309 -0
- package/src/link/Link.ts +284 -0
- package/src/link/index.ts +2 -0
- package/src/link/link-styles.generated.ts +3 -0
- package/src/link/link.shadow.css +15 -0
- package/src/ordered-list/OrderedList.test.ts +97 -0
- package/src/ordered-list/OrderedList.ts +84 -0
- package/src/ordered-list/index.ts +1 -0
- package/src/ordered-list/ordered-list-styles.generated.ts +3 -0
- package/src/ordered-list/ordered-list.shadow.css +11 -0
- package/src/paragraph/Paragraph.test.ts +143 -0
- package/src/paragraph/Paragraph.ts +77 -0
- package/src/paragraph/index.ts +2 -0
- package/src/paragraph/paragraph-styles.generated.ts +3 -0
- package/src/paragraph/paragraph.shadow.css +11 -0
- package/src/unordered-list/UnorderedList.test.ts +66 -0
- package/src/unordered-list/UnorderedList.ts +50 -0
- package/src/unordered-list/index.ts +1 -0
- package/src/unordered-list/unordered-list-styles.generated.ts +3 -0
- package/src/unordered-list/unordered-list.shadow.css +11 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Auto-generated — do not edit manually.
|
|
2
|
+
// Run: node scripts/build-css.js
|
|
3
|
+
export const iconPaths: Record<string, string[]> = {
|
|
4
|
+
'alert-triangle': ["M0 0h24v24H0z","M12 9v4","M10.363 3.591l-8.106 13.534a1.914 1.914 0 0 0 1.636 2.871h16.214a1.914 1.914 0 0 0 1.636 -2.87l-8.106 -13.536a1.914 1.914 0 0 0 -3.274 0","M12 16h.01"],
|
|
5
|
+
'archive': ["M0 0h24v24H0z","M3 6a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2","M5 8v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-10","M10 12l4 0"],
|
|
6
|
+
'arrow-down': ["M0 0h24v24H0z","M12 5l0 14","M18 13l-6 6","M6 13l6 6"],
|
|
7
|
+
'arrow-left': ["M5 12l14 0","M5 12l6 6","M5 12l6 -6"],
|
|
8
|
+
'arrow-narrow-down': ["M0 0h24v24H0z","M12 5l0 14","M16 15l-4 4","M8 15l4 4"],
|
|
9
|
+
'arrow-narrow-up': ["M0 0h24v24H0z","M12 5l0 14","M16 9l-4 -4","M8 9l4 -4"],
|
|
10
|
+
'arrow-right': ["M5 12l14 0","M13 18l6 -6","M13 6l6 6"],
|
|
11
|
+
'arrow-up': ["M0 0h24v24H0z","M12 5l0 14","M18 11l-6 -6","M6 11l6 -6"],
|
|
12
|
+
'arrows-sort': ["M0 0h24v24H0z","M3 9l4 -4l4 4m-4 -4v14","M21 15l-4 4l-4 -4m4 4v-14"],
|
|
13
|
+
'bell': ["M0 0h24v24H0z","M10 5a2 2 0 1 1 4 0a7 7 0 0 1 4 6v3a4 4 0 0 0 2 3h-16a4 4 0 0 0 2 -3v-3a7 7 0 0 1 4 -6","M9 17v1a3 3 0 0 0 6 0v-1"],
|
|
14
|
+
'calendar-event': ["M0 0h24v24H0z","M4 7a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2l0 -12","M16 3l0 4","M8 3l0 4","M4 11l16 0","M8 15h2v2h-2l0 -2"],
|
|
15
|
+
'check': ["M5 12l5 5l10 -10"],
|
|
16
|
+
'chevron-down': ["M6 9l6 6l6 -6"],
|
|
17
|
+
'chevron-left': ["M15 6l-6 6l6 6"],
|
|
18
|
+
'chevron-right': ["M9 6l6 6l-6 6"],
|
|
19
|
+
'chevron-up': ["M6 15l6 -6l6 6"],
|
|
20
|
+
'circle-check': ["M0 0h24v24H0z","M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0","M9 12l2 2l4 -4"],
|
|
21
|
+
'clock': ["M0 0h24v24H0z","M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0","M12 7v5l3 3"],
|
|
22
|
+
'dots-vertical': ["M0 0h24v24H0z","M11 12a1 1 0 1 0 2 0a1 1 0 1 0 -2 0","M11 19a1 1 0 1 0 2 0a1 1 0 1 0 -2 0","M11 5a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"],
|
|
23
|
+
'download': ["M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2","M7 11l5 5l5 -5","M12 4l0 12"],
|
|
24
|
+
'edit': ["M7 7h-1a2 2 0 0 0 -2 2v9a2 2 0 0 0 2 2h9a2 2 0 0 0 2 -2v-1","M20.385 6.585a2.1 2.1 0 0 0 -2.97 -2.97l-8.415 8.385v3h3l8.385 -8.415z","M16 5l3 3"],
|
|
25
|
+
'exclamation-circle': ["M0 0h24v24H0z","M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0","M12 9v4","M12 16v.01"],
|
|
26
|
+
'external-link': ["M0 0h24v24H0z","M12 6h-6a2 2 0 0 0 -2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-6","M11 13l9 -9","M15 4h5v5"],
|
|
27
|
+
'eye': ["M0 0h24v24H0z","M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0","M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6"],
|
|
28
|
+
'file-description': ["M0 0h24v24H0z","M14 3v4a1 1 0 0 0 1 1h4","M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2","M9 17h6","M9 13h6"],
|
|
29
|
+
'folder': ["M0 0h24v24H0z","M5 4h4l3 3h7a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-11a2 2 0 0 1 2 -2"],
|
|
30
|
+
'heart-filled': ["M0 0h24v24H0z","M6.979 3.074a6 6 0 0 1 4.988 1.425l.037 .033l.034 -.03a6 6 0 0 1 4.733 -1.44l.246 .036a6 6 0 0 1 3.364 10.008l-.18 .185l-.048 .041l-7.45 7.379a1 1 0 0 1 -1.313 .082l-.094 -.082l-7.493 -7.422a6 6 0 0 1 3.176 -10.215z"],
|
|
31
|
+
'heart': ["M0 0h24v24H0z","M19.5 12.572l-7.5 7.428l-7.5 -7.428a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572"],
|
|
32
|
+
'home': ["M5 12l-2 0l9 -9l9 9l-2 0","M5 12v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-7","M9 21v-6a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v6"],
|
|
33
|
+
'info-circle': ["M0 0h24v24H0z","M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0","M12 9h.01","M11 12h1v4h1"],
|
|
34
|
+
'loader': ["M0 0h24v24H0z","M12 6l0 -3","M16.25 7.75l2.15 -2.15","M18 12l3 0","M16.25 16.25l2.15 2.15","M12 18l0 3","M7.75 16.25l-2.15 2.15","M6 12l-3 0","M7.75 7.75l-2.15 -2.15"],
|
|
35
|
+
'mail': ["M0 0h24v24H0z","M3 7a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-10","M3 7l9 6l9 -6"],
|
|
36
|
+
'menu': ["M4 6l16 0","M4 12l16 0","M4 18l16 0"],
|
|
37
|
+
'message-circle': ["M0 0h24v24H0z","M3 20l1.3 -3.9c-2.324 -3.437 -1.426 -7.872 2.1 -10.374c3.526 -2.501 8.59 -2.296 11.845 .48c3.255 2.777 3.695 7.266 1.029 10.501c-2.666 3.235 -7.615 4.215 -11.574 2.293l-4.7 1"],
|
|
38
|
+
'minus': ["M5 12l14 0"],
|
|
39
|
+
'paperclip': ["M0 0h24v24H0z","M15 7l-6.5 6.5a1.5 1.5 0 0 0 3 3l6.5 -6.5a3 3 0 0 0 -6 -6l-6.5 6.5a4.5 4.5 0 0 0 9 9l6.5 -6.5"],
|
|
40
|
+
'pencil': ["M4 20h4l10.5 -10.5a2.828 2.828 0 1 0 -4 -4l-10.5 10.5v4","M13.5 6.5l4 4"],
|
|
41
|
+
'photo': ["M0 0h24v24H0z","M15 8h.01","M3 6a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v12a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3v-12","M3 16l5 -5c.928 -.893 2.072 -.893 3 0l5 5","M14 14l1 -1c.928 -.893 2.072 -.893 3 0l3 3"],
|
|
42
|
+
'plus': ["M12 5l0 14","M5 12l14 0"],
|
|
43
|
+
'printer': ["M0 0h24v24H0z","M17 17h2a2 2 0 0 0 2 -2v-4a2 2 0 0 0 -2 -2h-14a2 2 0 0 0 -2 2v4a2 2 0 0 0 2 2h2","M17 9v-4a2 2 0 0 0 -2 -2h-6a2 2 0 0 0 -2 2v4","M7 15a2 2 0 0 1 2 -2h6a2 2 0 0 1 2 2v4a2 2 0 0 1 -2 2h-6a2 2 0 0 1 -2 -2l0 -4"],
|
|
44
|
+
'search': ["M10 10m-7 0a7 7 0 1 0 14 0a7 7 0 1 0 -14 0","M21 21l-6 -6"],
|
|
45
|
+
'selector': ["M0 0h24v24H0z","M8 9l4 -4l4 4","M16 15l-4 4l-4 -4"],
|
|
46
|
+
'settings': ["M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065z","M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0"],
|
|
47
|
+
'sort-ascending': ["M0 0h24v24H0z","M4 6l7 0","M4 12l7 0","M4 18l9 0","M15 9l3 -3l3 3","M18 6l0 12"],
|
|
48
|
+
'sort-descending': ["M0 0h24v24H0z","M4 6l9 0","M4 12l7 0","M4 18l7 0","M15 15l3 3l3 -3","M18 6l0 12"],
|
|
49
|
+
'star-filled': ["M0 0h24v24H0z","M8.243 7.34l-6.38 .925l-.113 .023a1 1 0 0 0 -.44 1.684l4.622 4.499l-1.09 6.355l-.013 .11a1 1 0 0 0 1.464 .944l5.706 -3l5.693 3l.1 .046a1 1 0 0 0 1.352 -1.1l-1.091 -6.355l4.624 -4.5l.078 -.085a1 1 0 0 0 -.633 -1.62l-6.38 -.926l-2.852 -5.78a1 1 0 0 0 -1.794 0l-2.853 5.78z"],
|
|
50
|
+
'star': ["M12 17.75l-6.172 3.245l1.179 -6.873l-5 -4.867l6.9 -1l3.086 -6.253l3.086 6.253l6.9 1l-5 4.867l1.179 6.873z"],
|
|
51
|
+
'trash': ["M4 7l16 0","M10 11l0 6","M14 11l0 6","M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12","M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3"],
|
|
52
|
+
'upload': ["M0 0h24v24H0z","M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2","M7 9l5 -5l5 5","M12 4l0 12"],
|
|
53
|
+
'user': ["M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0","M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2"],
|
|
54
|
+
'x': ["M18 6l-12 12","M6 6l12 12"],
|
|
55
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// Auto-generated — do not edit manually.
|
|
2
|
+
// Source: icon.shadow.css + components-html source
|
|
3
|
+
export const iconStyles = "/**\n * Shadow DOM wrapper styles for the Icon Web Component.\n * The core icon styles are imported from the shared HTML/CSS source.\n */\n\n:host {\n display: inline-block;\n vertical-align: middle;\n line-height: 0;\n}\n\n/* Shared icon styles - single source of truth */\n/**\n * Icon Component Styles\n * Uses design tokens for sizing (coupled to typography)\n *\n * Usage:\n * <svg class=\"dsn-icon dsn-icon--lg\" ...>\n * <use href=\"...\" />\n * </svg>\n */\n\n.dsn-icon {\n /* Base styles */\n display: inline-block;\n vertical-align: middle;\n flex-shrink: 0;\n\n /* Default size (md) */\n width: var(--dsn-icon-size-md);\n height: var(--dsn-icon-size-md);\n}\n\n/* Size Variants - Using design tokens */\n.dsn-icon--sm {\n width: var(--dsn-icon-size-sm);\n height: var(--dsn-icon-size-sm);\n}\n\n.dsn-icon--lg {\n width: var(--dsn-icon-size-lg);\n height: var(--dsn-icon-size-lg);\n}\n\n.dsn-icon--xl {\n width: var(--dsn-icon-size-xl);\n height: var(--dsn-icon-size-xl);\n}\n\n.dsn-icon--2xl {\n width: var(--dsn-icon-size-2xl);\n height: var(--dsn-icon-size-2xl);\n}\n\n.dsn-icon--3xl {\n width: var(--dsn-icon-size-3xl);\n height: var(--dsn-icon-size-3xl);\n}\n\n.dsn-icon--4xl {\n width: var(--dsn-icon-size-4xl);\n height: var(--dsn-icon-size-4xl);\n}\n\n";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shadow DOM wrapper styles for the Icon Web Component.
|
|
3
|
+
* The core icon styles are imported from the shared HTML/CSS source.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
:host {
|
|
7
|
+
display: inline-block;
|
|
8
|
+
vertical-align: middle;
|
|
9
|
+
line-height: 0;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/* Shared icon styles - single source of truth */
|
|
13
|
+
@import '../../../components-html/src/icon/icon.css';
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dsn-starter-kit/components-web
|
|
3
|
+
* Web Components for the design system
|
|
4
|
+
*
|
|
5
|
+
* This package exports Web Components that can be registered manually or all at once.
|
|
6
|
+
* Components are NOT auto-registered on import - you must explicitly register them.
|
|
7
|
+
*
|
|
8
|
+
* @example Register all components at once
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { defineAllComponents } from '@dsn-starter-kit/components-web';
|
|
11
|
+
* defineAllComponents();
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* @example Register specific components
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { defineButton, defineIcon } from '@dsn-starter-kit/components-web';
|
|
17
|
+
* defineButton();
|
|
18
|
+
* defineIcon();
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @example Register with custom tag names
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { defineButton } from '@dsn-starter-kit/components-web';
|
|
24
|
+
* defineButton('my-custom-button');
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
// Internal imports for defineAllComponents
|
|
29
|
+
import { defineButton as _defineButton } from './button';
|
|
30
|
+
import { defineIcon as _defineIcon } from './icon';
|
|
31
|
+
import { defineParagraph as _defineParagraph } from './paragraph';
|
|
32
|
+
import { defineHeading as _defineHeading } from './heading';
|
|
33
|
+
import { defineLink as _defineLink } from './link';
|
|
34
|
+
import { defineUnorderedList as _defineUnorderedList } from './unordered-list';
|
|
35
|
+
import { defineOrderedList as _defineOrderedList } from './ordered-list';
|
|
36
|
+
|
|
37
|
+
// Button
|
|
38
|
+
export { DsnButton, defineButton } from './button';
|
|
39
|
+
export type { ButtonVariant, ButtonSize } from './button';
|
|
40
|
+
|
|
41
|
+
// Icon
|
|
42
|
+
export { DsnIcon, defineIcon } from './icon';
|
|
43
|
+
export type { IconSize, IconName } from './icon';
|
|
44
|
+
|
|
45
|
+
// Paragraph
|
|
46
|
+
export { DsnParagraph, defineParagraph } from './paragraph';
|
|
47
|
+
export type { ParagraphVariant } from './paragraph';
|
|
48
|
+
|
|
49
|
+
// Heading
|
|
50
|
+
export { DsnHeading, defineHeading } from './heading';
|
|
51
|
+
export type { HeadingLevel, HeadingAppearance } from './heading';
|
|
52
|
+
|
|
53
|
+
// Link
|
|
54
|
+
export { DsnLink, defineLink } from './link';
|
|
55
|
+
|
|
56
|
+
// Unordered List
|
|
57
|
+
export { DsnUnorderedList, defineUnorderedList } from './unordered-list';
|
|
58
|
+
|
|
59
|
+
// Ordered List
|
|
60
|
+
export { DsnOrderedList, defineOrderedList } from './ordered-list';
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Register all components with their default tag names.
|
|
64
|
+
* Call this once in your application entry point.
|
|
65
|
+
*
|
|
66
|
+
* Default tag names:
|
|
67
|
+
* - dsn-button
|
|
68
|
+
* - dsn-icon
|
|
69
|
+
* - dsn-paragraph
|
|
70
|
+
* - dsn-heading
|
|
71
|
+
* - dsn-link
|
|
72
|
+
* - dsn-unordered-list
|
|
73
|
+
* - dsn-ordered-list
|
|
74
|
+
*/
|
|
75
|
+
export function defineAllComponents(): void {
|
|
76
|
+
_defineButton();
|
|
77
|
+
_defineIcon();
|
|
78
|
+
_defineParagraph();
|
|
79
|
+
_defineHeading();
|
|
80
|
+
_defineLink();
|
|
81
|
+
_defineUnorderedList();
|
|
82
|
+
_defineOrderedList();
|
|
83
|
+
}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll, beforeEach, vi } from 'vitest';
|
|
2
|
+
import { DsnLink, defineLink } from './Link';
|
|
3
|
+
|
|
4
|
+
// Register the custom element once for all tests
|
|
5
|
+
beforeAll(() => {
|
|
6
|
+
defineLink();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
function createElement(attrs: Record<string, string> = {}): DsnLink {
|
|
10
|
+
const el = document.createElement('dsn-link') as DsnLink;
|
|
11
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
12
|
+
el.setAttribute(key, value);
|
|
13
|
+
}
|
|
14
|
+
document.body.appendChild(el);
|
|
15
|
+
return el;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getInternalAnchor(el: DsnLink): HTMLAnchorElement {
|
|
19
|
+
return el.shadowRoot!.querySelector('a')!;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe('DsnLink', () => {
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
document.body.innerHTML = '';
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('rendering', () => {
|
|
28
|
+
it('creates a shadow root', () => {
|
|
29
|
+
const el = createElement();
|
|
30
|
+
expect(el.shadowRoot).not.toBeNull();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('renders an internal anchor element', () => {
|
|
34
|
+
const el = createElement();
|
|
35
|
+
const anchor = getInternalAnchor(el);
|
|
36
|
+
expect(anchor).toBeInstanceOf(HTMLAnchorElement);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('renders a style element in shadow DOM', () => {
|
|
40
|
+
const el = createElement();
|
|
41
|
+
const style = el.shadowRoot!.querySelector('style');
|
|
42
|
+
expect(style).not.toBeNull();
|
|
43
|
+
expect(style!.textContent).toContain('.dsn-link');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('renders a default slot for content projection', () => {
|
|
47
|
+
const el = createElement();
|
|
48
|
+
const slot = el.shadowRoot!.querySelector('slot:not([name])');
|
|
49
|
+
expect(slot).not.toBeNull();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('renders an icon-start named slot', () => {
|
|
53
|
+
const el = createElement();
|
|
54
|
+
const slot = el.shadowRoot!.querySelector('slot[name="icon-start"]');
|
|
55
|
+
expect(slot).not.toBeNull();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('renders an icon-end named slot', () => {
|
|
59
|
+
const el = createElement();
|
|
60
|
+
const slot = el.shadowRoot!.querySelector('slot[name="icon-end"]');
|
|
61
|
+
expect(slot).not.toBeNull();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('renders slots in correct order: icon-start, default, icon-end', () => {
|
|
65
|
+
const el = createElement();
|
|
66
|
+
const anchor = getInternalAnchor(el);
|
|
67
|
+
const slots = anchor.querySelectorAll('slot');
|
|
68
|
+
expect(slots).toHaveLength(3);
|
|
69
|
+
expect(slots[0].getAttribute('name')).toBe('icon-start');
|
|
70
|
+
expect(slots[1].getAttribute('name')).toBeNull();
|
|
71
|
+
expect(slots[2].getAttribute('name')).toBe('icon-end');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('applies dsn-link class to internal anchor', () => {
|
|
75
|
+
const el = createElement();
|
|
76
|
+
const anchor = getInternalAnchor(el);
|
|
77
|
+
expect(anchor.classList.contains('dsn-link')).toBe(true);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('href attribute', () => {
|
|
82
|
+
it('sets href on internal anchor', () => {
|
|
83
|
+
const el = createElement({ href: '/about' });
|
|
84
|
+
const anchor = getInternalAnchor(el);
|
|
85
|
+
expect(anchor.getAttribute('href')).toBe('/about');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('defaults to no href', () => {
|
|
89
|
+
const el = createElement();
|
|
90
|
+
const anchor = getInternalAnchor(el);
|
|
91
|
+
expect(anchor.hasAttribute('href')).toBe(false);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('updates internal anchor when href changes', () => {
|
|
95
|
+
const el = createElement({ href: '/about' });
|
|
96
|
+
const anchor = getInternalAnchor(el);
|
|
97
|
+
expect(anchor.getAttribute('href')).toBe('/about');
|
|
98
|
+
|
|
99
|
+
el.href = '/contact';
|
|
100
|
+
expect(anchor.getAttribute('href')).toBe('/contact');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('removes href from internal anchor when set to null', () => {
|
|
104
|
+
const el = createElement({ href: '/about' });
|
|
105
|
+
const anchor = getInternalAnchor(el);
|
|
106
|
+
expect(anchor.getAttribute('href')).toBe('/about');
|
|
107
|
+
|
|
108
|
+
el.href = null;
|
|
109
|
+
expect(anchor.hasAttribute('href')).toBe(false);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
describe('target attribute', () => {
|
|
114
|
+
it('sets target on internal anchor', () => {
|
|
115
|
+
const el = createElement({ href: '/about', target: '_blank' });
|
|
116
|
+
const anchor = getInternalAnchor(el);
|
|
117
|
+
expect(anchor.getAttribute('target')).toBe('_blank');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('defaults to no target', () => {
|
|
121
|
+
const el = createElement();
|
|
122
|
+
const anchor = getInternalAnchor(el);
|
|
123
|
+
expect(anchor.hasAttribute('target')).toBe(false);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe('rel attribute', () => {
|
|
128
|
+
it('sets rel on internal anchor', () => {
|
|
129
|
+
const el = createElement({ href: '/about', rel: 'noopener noreferrer' });
|
|
130
|
+
const anchor = getInternalAnchor(el);
|
|
131
|
+
expect(anchor.getAttribute('rel')).toBe('noopener noreferrer');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('defaults to no rel', () => {
|
|
135
|
+
const el = createElement();
|
|
136
|
+
const anchor = getInternalAnchor(el);
|
|
137
|
+
expect(anchor.hasAttribute('rel')).toBe(false);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('disabled state', () => {
|
|
142
|
+
it('sets aria-disabled on internal anchor when disabled', () => {
|
|
143
|
+
const el = createElement({ href: '/about', disabled: '' });
|
|
144
|
+
const anchor = getInternalAnchor(el);
|
|
145
|
+
expect(anchor.getAttribute('aria-disabled')).toBe('true');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('removes href from internal anchor when disabled', () => {
|
|
149
|
+
const el = createElement({ href: '/about', disabled: '' });
|
|
150
|
+
const anchor = getInternalAnchor(el);
|
|
151
|
+
expect(anchor.hasAttribute('href')).toBe(false);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('sets tabindex to -1 when disabled', () => {
|
|
155
|
+
const el = createElement({ href: '/about', disabled: '' });
|
|
156
|
+
const anchor = getInternalAnchor(el);
|
|
157
|
+
expect(anchor.getAttribute('tabindex')).toBe('-1');
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('restores href when disabled is removed', () => {
|
|
161
|
+
const el = createElement({ href: '/about', disabled: '' });
|
|
162
|
+
const anchor = getInternalAnchor(el);
|
|
163
|
+
expect(anchor.hasAttribute('href')).toBe(false);
|
|
164
|
+
|
|
165
|
+
el.disabled = false;
|
|
166
|
+
expect(anchor.getAttribute('href')).toBe('/about');
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('removes aria-disabled when disabled is removed', () => {
|
|
170
|
+
const el = createElement({ href: '/about', disabled: '' });
|
|
171
|
+
const anchor = getInternalAnchor(el);
|
|
172
|
+
expect(anchor.getAttribute('aria-disabled')).toBe('true');
|
|
173
|
+
|
|
174
|
+
el.disabled = false;
|
|
175
|
+
expect(anchor.hasAttribute('aria-disabled')).toBe(false);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('removes tabindex when disabled is removed', () => {
|
|
179
|
+
const el = createElement({ href: '/about', disabled: '' });
|
|
180
|
+
const anchor = getInternalAnchor(el);
|
|
181
|
+
expect(anchor.getAttribute('tabindex')).toBe('-1');
|
|
182
|
+
|
|
183
|
+
el.disabled = false;
|
|
184
|
+
expect(anchor.hasAttribute('tabindex')).toBe(false);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('reflects disabled property to attribute', () => {
|
|
188
|
+
const el = createElement();
|
|
189
|
+
el.disabled = true;
|
|
190
|
+
expect(el.hasAttribute('disabled')).toBe(true);
|
|
191
|
+
|
|
192
|
+
el.disabled = false;
|
|
193
|
+
expect(el.hasAttribute('disabled')).toBe(false);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
describe('current state', () => {
|
|
198
|
+
it('sets aria-current="page" on internal anchor when current', () => {
|
|
199
|
+
const el = createElement({ href: '/dashboard', current: '' });
|
|
200
|
+
const anchor = getInternalAnchor(el);
|
|
201
|
+
expect(anchor.getAttribute('aria-current')).toBe('page');
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('removes aria-current when current is removed', () => {
|
|
205
|
+
const el = createElement({ href: '/dashboard', current: '' });
|
|
206
|
+
const anchor = getInternalAnchor(el);
|
|
207
|
+
expect(anchor.getAttribute('aria-current')).toBe('page');
|
|
208
|
+
|
|
209
|
+
el.current = false;
|
|
210
|
+
expect(anchor.hasAttribute('aria-current')).toBe(false);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('reflects current property to attribute', () => {
|
|
214
|
+
const el = createElement();
|
|
215
|
+
el.current = true;
|
|
216
|
+
expect(el.hasAttribute('current')).toBe(true);
|
|
217
|
+
|
|
218
|
+
el.current = false;
|
|
219
|
+
expect(el.hasAttribute('current')).toBe(false);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
describe('size attribute', () => {
|
|
224
|
+
it('does not apply size class by default', () => {
|
|
225
|
+
const el = createElement();
|
|
226
|
+
const anchor = getInternalAnchor(el);
|
|
227
|
+
expect(anchor.className).toBe('dsn-link');
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it('applies size class when size is set to small', () => {
|
|
231
|
+
const el = createElement({ size: 'small' });
|
|
232
|
+
const anchor = getInternalAnchor(el);
|
|
233
|
+
expect(anchor.classList.contains('dsn-link--size-small')).toBe(true);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it('applies size class when size is set to default', () => {
|
|
237
|
+
const el = createElement({ size: 'default' });
|
|
238
|
+
const anchor = getInternalAnchor(el);
|
|
239
|
+
expect(anchor.classList.contains('dsn-link--size-default')).toBe(true);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it('applies size class when size is set to large', () => {
|
|
243
|
+
const el = createElement({ size: 'large' });
|
|
244
|
+
const anchor = getInternalAnchor(el);
|
|
245
|
+
expect(anchor.classList.contains('dsn-link--size-large')).toBe(true);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('updates class when size changes', () => {
|
|
249
|
+
const el = createElement({ size: 'small' });
|
|
250
|
+
const anchor = getInternalAnchor(el);
|
|
251
|
+
expect(anchor.classList.contains('dsn-link--size-small')).toBe(true);
|
|
252
|
+
|
|
253
|
+
el.size = 'large';
|
|
254
|
+
expect(anchor.classList.contains('dsn-link--size-large')).toBe(true);
|
|
255
|
+
expect(anchor.classList.contains('dsn-link--size-small')).toBe(false);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it('returns default from size property when no attribute set', () => {
|
|
259
|
+
const el = createElement();
|
|
260
|
+
expect(el.size).toBe('default');
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('reflects size property to attribute', () => {
|
|
264
|
+
const el = createElement();
|
|
265
|
+
el.size = 'large';
|
|
266
|
+
expect(el.getAttribute('size')).toBe('large');
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
describe('focus delegation', () => {
|
|
271
|
+
it('delegates focus to internal anchor', () => {
|
|
272
|
+
const el = createElement({ href: '/about' });
|
|
273
|
+
const anchor = getInternalAnchor(el);
|
|
274
|
+
const focusSpy = vi.spyOn(anchor, 'focus');
|
|
275
|
+
|
|
276
|
+
el.focus();
|
|
277
|
+
expect(focusSpy).toHaveBeenCalled();
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it('delegates blur to internal anchor', () => {
|
|
281
|
+
const el = createElement({ href: '/about' });
|
|
282
|
+
const anchor = getInternalAnchor(el);
|
|
283
|
+
const blurSpy = vi.spyOn(anchor, 'blur');
|
|
284
|
+
|
|
285
|
+
el.blur();
|
|
286
|
+
expect(blurSpy).toHaveBeenCalled();
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('delegates click to internal anchor', () => {
|
|
290
|
+
const el = createElement({ href: '/about' });
|
|
291
|
+
const anchor = getInternalAnchor(el);
|
|
292
|
+
const clickSpy = vi.spyOn(anchor, 'click');
|
|
293
|
+
|
|
294
|
+
el.click();
|
|
295
|
+
expect(clickSpy).toHaveBeenCalled();
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
describe('defineLink', () => {
|
|
301
|
+
it('does not throw when called with an already-registered tag', () => {
|
|
302
|
+
expect(() => defineLink('dsn-link')).not.toThrow();
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('registers a custom element with the default tag name', () => {
|
|
306
|
+
const el = document.createElement('dsn-link');
|
|
307
|
+
expect(el).toBeInstanceOf(DsnLink);
|
|
308
|
+
});
|
|
309
|
+
});
|