@dataengineeringformachinelearning/viking-ui 1.0.2 → 3.0.0-alpha.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/README.md +180 -41
- package/dist/deml-components.css +1122 -0
- package/dist/design-tokens.css +688 -0
- package/dist/elements/button/viking-button.d.ts +14 -0
- package/dist/elements/card/viking-card.d.ts +8 -0
- package/dist/elements/core/dom.d.ts +4 -0
- package/dist/elements/core/styles.d.ts +2 -0
- package/dist/elements/modal/viking-modal.d.ts +15 -0
- package/dist/fonts/inter/InterVariable-Italic.woff2 +0 -0
- package/dist/fonts/inter/InterVariable.woff2 +0 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4051 -0
- package/dist/lib/core/brand-icons.d.ts +29 -0
- package/dist/lib/core/icons.d.ts +132 -0
- package/dist/lib/core/integration-brand-icons.d.ts +18 -0
- package/dist/lib/core/lucide-paths.generated.d.ts +90 -0
- package/dist/lib/site-drakkar/site-drakkar.config.d.ts +50 -0
- package/dist/lib/site-drakkar/suite-search-items.d.ts +17 -0
- package/dist/viking-components.css +1837 -0
- package/dist/viking-tokens.json +318 -0
- package/dist/viking-ui-elements.js +1750 -0
- package/dist/viking-ui.css +1 -0
- package/dist/web/badge/viking-badge-wc.d.ts +28 -0
- package/dist/web/button/viking-button-wc.d.ts +28 -0
- package/dist/web/callout/viking-callout-wc.d.ts +27 -0
- package/dist/web/card/viking-card-wc.d.ts +29 -0
- package/dist/web/core/base.d.ts +12 -0
- package/dist/web/core/dom.d.ts +11 -0
- package/dist/web/core/icons-inline.d.ts +7 -0
- package/dist/web/core/styles.d.ts +12 -0
- package/dist/web/core/types.d.ts +10 -0
- package/dist/web/field/viking-field-wc.d.ts +32 -0
- package/dist/web/index.d.ts +15 -0
- package/dist/web/input/viking-input-wc.d.ts +32 -0
- package/dist/web/modal/viking-modal-wc.d.ts +50 -0
- package/dist/web/search-palette/viking-search-palette-wc.d.ts +64 -0
- package/dist/web/select/viking-select-wc.d.ts +48 -0
- package/dist/web/suite-header/viking-suite-header-wc.d.ts +36 -0
- package/dist/web/suite-search-palette/viking-suite-search-palette-wc.d.ts +39 -0
- package/dist/web/theme-toggle/viking-theme-toggle-wc.d.ts +19 -0
- package/dist/web/types.d.ts +40 -0
- package/dist/web-components/index.d.ts +1 -0
- package/dist/web-components.js +1750 -0
- package/dist/widget.js +1182 -0
- package/package.json +89 -30
- package/src/assets/fonts/inter/InterVariable-Italic.woff2 +0 -0
- package/src/assets/fonts/inter/InterVariable.woff2 +0 -0
- package/src/elements/button/viking-button.ts +201 -0
- package/src/elements/card/viking-card.ts +60 -0
- package/src/elements/core/dom.ts +33 -0
- package/src/elements/core/styles.ts +28 -0
- package/src/elements/modal/viking-modal.ts +154 -0
- package/src/index.ts +1 -0
- package/src/lib/core/brand-icons.ts +62 -0
- package/src/lib/core/icons.ts +206 -0
- package/src/lib/core/integration-brand-icons.ts +77 -0
- package/src/lib/core/lucide-paths.generated.ts +130 -0
- package/src/lib/site-drakkar/site-drakkar.config.ts +295 -0
- package/src/lib/site-drakkar/suite-search-items.ts +246 -0
- package/src/styles/_buttons.scss +301 -0
- package/src/styles/_component-primitives.scss +183 -0
- package/src/styles/_drakkar-buttons.scss +85 -0
- package/src/styles/_fonts.scss +22 -0
- package/src/styles/_forms.scss +66 -0
- package/src/styles/_input.scss +106 -0
- package/src/styles/_layout-enforcement.scss +166 -0
- package/src/styles/_layout-rhythm.scss +158 -0
- package/src/styles/_legacy-aliases.scss +212 -0
- package/src/styles/_series-colors.scss +24 -0
- package/src/styles/_static-primitives.scss +857 -0
- package/src/styles/_typography.scss +87 -0
- package/src/styles/_variables.scss +527 -0
- package/src/styles/components/a11y.scss +90 -0
- package/src/styles/components/badges.scss +102 -0
- package/src/styles/components/extracted-utilities.scss +459 -0
- package/src/styles/components/footer.scss +155 -0
- package/src/styles/components/icon-heading.scss +47 -0
- package/src/styles/components/icon-inline.scss +78 -0
- package/src/styles/components/layout.scss +59 -0
- package/src/styles/components/utilities.scss +131 -0
- package/src/styles/components/viking-inspired.scss +204 -0
- package/src/styles/components/whitepaper-cta.scss +130 -0
- package/src/styles/components-bundle.scss +9 -0
- package/src/styles/components.scss +175 -0
- package/src/styles/deml-components.scss +10 -0
- package/src/styles/index.scss +8 -0
- package/src/styles/layout-shell.scss +39 -11
- package/src/styles/page-shell.scss +663 -33
- package/src/styles/static-navbar.scss +862 -146
- package/src/styles/surfaces/backend.scss +142 -0
- package/src/styles/surfaces/docs-global.scss +73 -0
- package/src/styles/surfaces/docs-shell.scss +412 -0
- package/src/styles/surfaces/docs-showcase.scss +1051 -0
- package/src/styles/surfaces/marketing-cta.scss +62 -0
- package/src/styles/surfaces/marketing-docs-bento.scss +67 -0
- package/src/styles/surfaces/marketing-global.scss +748 -0
- package/src/styles/surfaces/marketing-landing.scss +1260 -0
- package/src/styles/surfaces/marketing-publication.scss +535 -0
- package/src/styles/surfaces/marketing-theme.scss +14 -0
- package/src/styles/surfaces/swagger-ui.scss +921 -0
- package/src/styles/tokens-export.scss +18 -0
- package/src/styles/tokens.scss +5 -0
- package/src/styles/viking-ui-bundle.scss +20 -2
- package/src/styles/viking-ui.scss +213 -51
- package/src/tokens/viking-tokens.json +318 -0
- package/src/web/badge/viking-badge-wc.ts +116 -0
- package/src/web/button/viking-button-wc.ts +165 -0
- package/src/web/callout/viking-callout-wc.ts +105 -0
- package/src/web/card/viking-card-wc.ts +66 -0
- package/src/web/core/base.ts +56 -0
- package/src/web/core/dom.ts +53 -0
- package/src/web/core/icons-inline.ts +44 -0
- package/src/web/core/styles.ts +1138 -0
- package/src/web/core/types.ts +19 -0
- package/src/web/field/viking-field-wc.ts +154 -0
- package/src/web/index.ts +73 -0
- package/src/web/input/viking-input-wc.ts +211 -0
- package/src/web/modal/viking-modal-wc.ts +187 -0
- package/src/web/search-palette/viking-search-palette-wc.ts +494 -0
- package/src/web/select/viking-select-wc.ts +218 -0
- package/src/web/suite-header/viking-suite-header-wc.ts +714 -0
- package/src/web/suite-search-palette/viking-suite-search-palette-wc.ts +234 -0
- package/src/web/theme-toggle/viking-theme-toggle-wc.ts +139 -0
- package/src/web/types.ts +37 -0
- package/src/web-components/index.ts +1 -0
- package/fesm2022/dataengineeringformachinelearning-viking-ui.mjs +0 -6114
- package/fesm2022/dataengineeringformachinelearning-viking-ui.mjs.map +0 -1
- package/types/dataengineeringformachinelearning-viking-ui.d.ts +0 -1397
- package/viking.manifest.json +0 -238
package/package.json
CHANGED
|
@@ -1,38 +1,97 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dataengineeringformachinelearning/viking-ui",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Viking-UI
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"
|
|
3
|
+
"version": "3.0.0-alpha.2",
|
|
4
|
+
"description": "Universal Viking-UI design system for Astro, Angular, and Django.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"private": false,
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"style": "./dist/viking-ui.css",
|
|
12
|
+
"browser": "./dist/viking-ui-elements.js",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/dataengineeringformachinelearning/dataengineeringformachinelearning.git",
|
|
16
|
+
"directory": "packages/viking-ui"
|
|
17
|
+
},
|
|
14
18
|
"publishConfig": {
|
|
15
19
|
"access": "public"
|
|
16
20
|
},
|
|
17
|
-
"peerDependencies": {
|
|
18
|
-
"@angular/common": "^22.0.0",
|
|
19
|
-
"@angular/core": "^22.0.0",
|
|
20
|
-
"@angular/forms": "^22.0.0"
|
|
21
|
-
},
|
|
22
|
-
"dependencies": {
|
|
23
|
-
"tslib": "^2.3.0"
|
|
24
|
-
},
|
|
25
|
-
"sideEffects": false,
|
|
26
|
-
"module": "fesm2022/dataengineeringformachinelearning-viking-ui.mjs",
|
|
27
|
-
"typings": "types/dataengineeringformachinelearning-viking-ui.d.ts",
|
|
28
21
|
"exports": {
|
|
29
|
-
"./package.json": {
|
|
30
|
-
"default": "./package.json"
|
|
31
|
-
},
|
|
32
22
|
".": {
|
|
33
|
-
"types": "./
|
|
34
|
-
"
|
|
35
|
-
}
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"import": "./dist/index.js"
|
|
25
|
+
},
|
|
26
|
+
"./dist/index.js": "./dist/index.js",
|
|
27
|
+
"./dist/viking-ui.css": "./dist/viking-ui.css",
|
|
28
|
+
"./dist/viking-ui-elements.js": "./dist/viking-ui-elements.js",
|
|
29
|
+
"./dist/web-components.js": "./dist/web-components.js",
|
|
30
|
+
"./dist/widget.js": "./dist/widget.js",
|
|
31
|
+
"./elements": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"import": "./dist/web-components.js",
|
|
34
|
+
"default": "./dist/web-components.js"
|
|
35
|
+
},
|
|
36
|
+
"./elements.js": "./dist/viking-ui-elements.js",
|
|
37
|
+
"./viking-ui-elements.js": "./dist/viking-ui-elements.js",
|
|
38
|
+
"./web-components.js": "./dist/web-components.js",
|
|
39
|
+
"./web-components": {
|
|
40
|
+
"types": "./dist/index.d.ts",
|
|
41
|
+
"import": "./dist/web-components.js",
|
|
42
|
+
"default": "./dist/web-components.js"
|
|
43
|
+
},
|
|
44
|
+
"./css": "./dist/viking-ui.css",
|
|
45
|
+
"./css/index.css": "./dist/viking-ui.css",
|
|
46
|
+
"./css/viking-ui.css": "./dist/viking-ui.css",
|
|
47
|
+
"./css/design-tokens.css": "./dist/design-tokens.css",
|
|
48
|
+
"./css/viking-components.css": "./dist/viking-components.css",
|
|
49
|
+
"./css/deml-components.css": "./dist/deml-components.css",
|
|
50
|
+
"./css/tokens.css": "./dist/design-tokens.css",
|
|
51
|
+
"./css/components.css": "./dist/viking-components.css",
|
|
52
|
+
"./design-tokens.css": "./dist/design-tokens.css",
|
|
53
|
+
"./tokens.css": "./dist/design-tokens.css",
|
|
54
|
+
"./tokens": "./dist/viking-tokens.json",
|
|
55
|
+
"./tokens.json": "./dist/viking-tokens.json",
|
|
56
|
+
"./viking-tokens.json": "./dist/viking-tokens.json",
|
|
57
|
+
"./components.css": "./dist/viking-components.css",
|
|
58
|
+
"./deml-components.css": "./dist/deml-components.css",
|
|
59
|
+
"./viking-ui.css": "./dist/viking-ui.css",
|
|
60
|
+
"./package.json": "./package.json"
|
|
36
61
|
},
|
|
37
|
-
"
|
|
38
|
-
|
|
62
|
+
"files": [
|
|
63
|
+
"dist",
|
|
64
|
+
"src",
|
|
65
|
+
"README.md"
|
|
66
|
+
],
|
|
67
|
+
"scripts": {
|
|
68
|
+
"clean": "rm -rf dist",
|
|
69
|
+
"build": "npm run clean && npm run build:css && npm run build:elements",
|
|
70
|
+
"build:css": "node scripts/build-css.mjs",
|
|
71
|
+
"build:elements": "node scripts/build-elements.mjs",
|
|
72
|
+
"storybook": "npm run build:css && storybook dev --config-dir .storybook --port 6006",
|
|
73
|
+
"build-storybook": "npm run build:css && storybook build --config-dir .storybook --output-dir ./storybook-static",
|
|
74
|
+
"chromatic": "npm run build-storybook && chromatic --project-token=${CHROMATIC_PROJECT_TOKEN} --exit-zero-on-changes",
|
|
75
|
+
"validate": "node ../../scripts/validate_viking_ui_assets.mjs",
|
|
76
|
+
"test": "node --test test/*.test.mjs",
|
|
77
|
+
"pack:check": "npm pack --dry-run",
|
|
78
|
+
"typecheck": "tsc --project tsconfig.json --noEmit"
|
|
79
|
+
},
|
|
80
|
+
"sideEffects": [
|
|
81
|
+
"./dist/viking-ui-elements.js",
|
|
82
|
+
"./dist/viking-ui.css",
|
|
83
|
+
"./dist/design-tokens.css",
|
|
84
|
+
"./dist/viking-components.css",
|
|
85
|
+
"./dist/deml-components.css",
|
|
86
|
+
"./src/index.ts"
|
|
87
|
+
],
|
|
88
|
+
"devDependencies": {
|
|
89
|
+
"@chromatic-com/storybook": "^3.2.7",
|
|
90
|
+
"@storybook/addon-a11y": "^8.6.12",
|
|
91
|
+
"@storybook/addon-essentials": "^8.6.12",
|
|
92
|
+
"@storybook/html": "^8.6.12",
|
|
93
|
+
"esbuild": "^0.28.1",
|
|
94
|
+
"sass": "^1.101.0",
|
|
95
|
+
"typescript": "~6.0.3"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import {
|
|
2
|
+
attributeValue,
|
|
3
|
+
defineVikingElement,
|
|
4
|
+
HTMLElementBase,
|
|
5
|
+
readBooleanAttribute,
|
|
6
|
+
} from "../core/dom";
|
|
7
|
+
import { attachStyles, resetStyles } from "../core/styles";
|
|
8
|
+
|
|
9
|
+
const variants = new Set([
|
|
10
|
+
"outline",
|
|
11
|
+
"primary",
|
|
12
|
+
"secondary",
|
|
13
|
+
"danger",
|
|
14
|
+
"ghost",
|
|
15
|
+
]);
|
|
16
|
+
const sizes = new Set(["sm", "md"]);
|
|
17
|
+
|
|
18
|
+
const styles = `
|
|
19
|
+
${resetStyles}
|
|
20
|
+
|
|
21
|
+
:host {
|
|
22
|
+
display: inline-flex;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
:host([full-width]) {
|
|
26
|
+
display: flex;
|
|
27
|
+
width: 100%;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.control {
|
|
31
|
+
display: inline-flex;
|
|
32
|
+
width: auto;
|
|
33
|
+
min-width: var(--viking-btn-min-width, 120px);
|
|
34
|
+
min-height: var(--viking-control-height);
|
|
35
|
+
align-items: center;
|
|
36
|
+
justify-content: center;
|
|
37
|
+
gap: var(--viking-space-1);
|
|
38
|
+
padding: 0 var(--viking-control-padding-x);
|
|
39
|
+
border: 1px solid var(--viking-border-strong);
|
|
40
|
+
border-radius: var(--viking-radius);
|
|
41
|
+
background: var(--viking-surface);
|
|
42
|
+
color: var(--viking-text);
|
|
43
|
+
box-shadow: var(--viking-shadow-sm);
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
font: inherit;
|
|
46
|
+
font-size: var(--viking-font-size-sm);
|
|
47
|
+
font-weight: var(--viking-font-weight-semibold);
|
|
48
|
+
letter-spacing: var(--viking-letter-spacing-wide);
|
|
49
|
+
line-height: var(--viking-line-height-snug);
|
|
50
|
+
text-decoration: none;
|
|
51
|
+
transition: var(--viking-transition-interactive);
|
|
52
|
+
user-select: none;
|
|
53
|
+
white-space: nowrap;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
:host([full-width]) .control {
|
|
57
|
+
width: 100%;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.control:hover:not(:disabled):not([aria-busy='true']) {
|
|
61
|
+
border-color: color-mix(in srgb, var(--viking-accent) 45%, var(--viking-border-strong));
|
|
62
|
+
transform: translateY(var(--viking-state-hover-lift));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.control:focus-visible {
|
|
66
|
+
outline: var(--viking-ring-width) solid var(--viking-ring);
|
|
67
|
+
outline-offset: var(--viking-ring-offset);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.control:disabled,
|
|
71
|
+
.control[aria-busy='true'] {
|
|
72
|
+
cursor: not-allowed;
|
|
73
|
+
opacity: var(--viking-state-disabled-opacity);
|
|
74
|
+
transform: none;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.control[data-size='sm'] {
|
|
78
|
+
min-height: var(--viking-control-height-sm);
|
|
79
|
+
min-width: auto;
|
|
80
|
+
padding-inline: var(--viking-space-2);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.control[data-variant='primary'] {
|
|
84
|
+
border-color: color-mix(in srgb, var(--viking-accent) 82%, var(--viking-black));
|
|
85
|
+
background: var(--viking-accent);
|
|
86
|
+
color: var(--viking-accent-content);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.control[data-variant='secondary'] {
|
|
90
|
+
border-color: color-mix(in srgb, var(--viking-accent-secondary) 82%, var(--viking-black));
|
|
91
|
+
background: var(--viking-accent-secondary);
|
|
92
|
+
color: var(--viking-accent-secondary-content);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.control[data-variant='danger'] {
|
|
96
|
+
border-color: color-mix(in srgb, var(--viking-danger) 82%, var(--viking-black));
|
|
97
|
+
background: var(--viking-danger);
|
|
98
|
+
color: var(--viking-on-danger);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.control[data-variant='ghost'] {
|
|
102
|
+
min-width: auto;
|
|
103
|
+
border-color: transparent;
|
|
104
|
+
background: transparent;
|
|
105
|
+
box-shadow: none;
|
|
106
|
+
}
|
|
107
|
+
`;
|
|
108
|
+
|
|
109
|
+
export class VikingButton extends HTMLElementBase {
|
|
110
|
+
static readonly tagName = "viking-button";
|
|
111
|
+
|
|
112
|
+
static get observedAttributes(): string[] {
|
|
113
|
+
return [
|
|
114
|
+
"variant",
|
|
115
|
+
"size",
|
|
116
|
+
"type",
|
|
117
|
+
"href",
|
|
118
|
+
"target",
|
|
119
|
+
"disabled",
|
|
120
|
+
"loading",
|
|
121
|
+
"aria-label",
|
|
122
|
+
];
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private readonly shadowRootRef: ShadowRoot;
|
|
126
|
+
private control: HTMLAnchorElement | HTMLButtonElement | null = null;
|
|
127
|
+
|
|
128
|
+
constructor() {
|
|
129
|
+
super();
|
|
130
|
+
this.shadowRootRef = this.attachShadow({ mode: "open" });
|
|
131
|
+
attachStyles(this.shadowRootRef, styles);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
connectedCallback(): void {
|
|
135
|
+
this.render();
|
|
136
|
+
this.control?.addEventListener("click", this.handleClick);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
disconnectedCallback(): void {
|
|
140
|
+
this.control?.removeEventListener("click", this.handleClick);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
attributeChangedCallback(): void {
|
|
144
|
+
if (this.isConnected) {
|
|
145
|
+
this.render();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private readonly handleClick = (event: Event): void => {
|
|
150
|
+
if (
|
|
151
|
+
readBooleanAttribute(this, "disabled") ||
|
|
152
|
+
readBooleanAttribute(this, "loading")
|
|
153
|
+
) {
|
|
154
|
+
event.preventDefault();
|
|
155
|
+
event.stopPropagation();
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
this.dispatchEvent(
|
|
160
|
+
new CustomEvent("viking-press", {
|
|
161
|
+
bubbles: true,
|
|
162
|
+
composed: true,
|
|
163
|
+
detail: { sourceEvent: event },
|
|
164
|
+
}),
|
|
165
|
+
);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
private render(): void {
|
|
169
|
+
const href = this.getAttribute("href");
|
|
170
|
+
const tag = href ? "a" : "button";
|
|
171
|
+
const variant = attributeValue(this, "variant", "outline", variants);
|
|
172
|
+
const size = attributeValue(this, "size", "md", sizes);
|
|
173
|
+
const disabled =
|
|
174
|
+
readBooleanAttribute(this, "disabled") ||
|
|
175
|
+
readBooleanAttribute(this, "loading");
|
|
176
|
+
const label = this.getAttribute("aria-label");
|
|
177
|
+
const target = this.getAttribute("target");
|
|
178
|
+
|
|
179
|
+
this.shadowRootRef.innerHTML = `
|
|
180
|
+
<${tag}
|
|
181
|
+
part="control"
|
|
182
|
+
class="control"
|
|
183
|
+
data-variant="${variant}"
|
|
184
|
+
data-size="${size}"
|
|
185
|
+
${href ? `href="${href}"` : `type="${this.getAttribute("type") ?? "button"}"`}
|
|
186
|
+
${target ? `target="${target}"` : ""}
|
|
187
|
+
${target === "_blank" ? 'rel="noopener noreferrer"' : ""}
|
|
188
|
+
${disabled ? 'disabled aria-disabled="true"' : ""}
|
|
189
|
+
${readBooleanAttribute(this, "loading") ? 'aria-busy="true"' : ""}
|
|
190
|
+
${label ? `aria-label="${label}"` : ""}
|
|
191
|
+
>
|
|
192
|
+
<slot></slot>
|
|
193
|
+
</${tag}>
|
|
194
|
+
`;
|
|
195
|
+
this.control = this.shadowRootRef.querySelector(tag);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export const registerVikingButton = (): void => {
|
|
200
|
+
defineVikingElement(VikingButton.tagName, VikingButton);
|
|
201
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { defineVikingElement, HTMLElementBase } from "../core/dom";
|
|
2
|
+
import { attachStyles, resetStyles } from "../core/styles";
|
|
3
|
+
|
|
4
|
+
const styles = `
|
|
5
|
+
${resetStyles}
|
|
6
|
+
|
|
7
|
+
:host {
|
|
8
|
+
display: block;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.card {
|
|
12
|
+
display: grid;
|
|
13
|
+
gap: var(--viking-space-2);
|
|
14
|
+
padding: var(--viking-card-padding);
|
|
15
|
+
border: 1px solid var(--viking-border);
|
|
16
|
+
border-radius: var(--viking-radius-lg);
|
|
17
|
+
background: var(--viking-surface-recipe);
|
|
18
|
+
color: var(--viking-text);
|
|
19
|
+
box-shadow: var(--viking-shadow-sm);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
:host([compact]) .card {
|
|
23
|
+
padding: var(--viking-card-padding-compact);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
::slotted([slot='header']) {
|
|
27
|
+
color: var(--viking-text);
|
|
28
|
+
font-weight: var(--viking-font-weight-semibold);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
::slotted([slot='footer']) {
|
|
32
|
+
color: var(--viking-text-muted);
|
|
33
|
+
}
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
export class VikingCard extends HTMLElementBase {
|
|
37
|
+
static readonly tagName = "viking-card";
|
|
38
|
+
|
|
39
|
+
private readonly shadowRootRef: ShadowRoot;
|
|
40
|
+
|
|
41
|
+
constructor() {
|
|
42
|
+
super();
|
|
43
|
+
this.shadowRootRef = this.attachShadow({ mode: "open" });
|
|
44
|
+
attachStyles(this.shadowRootRef, styles);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
connectedCallback(): void {
|
|
48
|
+
this.shadowRootRef.innerHTML = `
|
|
49
|
+
<article class="card" part="surface">
|
|
50
|
+
<slot name="header"></slot>
|
|
51
|
+
<slot></slot>
|
|
52
|
+
<slot name="footer"></slot>
|
|
53
|
+
</article>
|
|
54
|
+
`;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const registerVikingCard = (): void => {
|
|
59
|
+
defineVikingElement(VikingCard.tagName, VikingCard);
|
|
60
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const HTMLElementBase: typeof HTMLElement =
|
|
2
|
+
typeof HTMLElement === "undefined"
|
|
3
|
+
? (class {} as unknown as typeof HTMLElement)
|
|
4
|
+
: HTMLElement;
|
|
5
|
+
|
|
6
|
+
export const defineVikingElement = (
|
|
7
|
+
tagName: string,
|
|
8
|
+
constructor: CustomElementConstructor,
|
|
9
|
+
): void => {
|
|
10
|
+
if (typeof customElements === "undefined") {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (!customElements.get(tagName)) {
|
|
15
|
+
customElements.define(tagName, constructor);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const readBooleanAttribute = (
|
|
20
|
+
element: HTMLElement,
|
|
21
|
+
name: string,
|
|
22
|
+
): boolean =>
|
|
23
|
+
element.hasAttribute(name) && element.getAttribute(name) !== "false";
|
|
24
|
+
|
|
25
|
+
export const attributeValue = (
|
|
26
|
+
element: HTMLElement,
|
|
27
|
+
name: string,
|
|
28
|
+
fallback: string,
|
|
29
|
+
allowed?: ReadonlySet<string>,
|
|
30
|
+
): string => {
|
|
31
|
+
const value = element.getAttribute(name) ?? fallback;
|
|
32
|
+
return allowed && !allowed.has(value) ? fallback : value;
|
|
33
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const resetStyles = `
|
|
2
|
+
:host {
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
font-family: var(--viking-font-family);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
*,
|
|
8
|
+
*::before,
|
|
9
|
+
*::after {
|
|
10
|
+
box-sizing: inherit;
|
|
11
|
+
}
|
|
12
|
+
`;
|
|
13
|
+
|
|
14
|
+
export const attachStyles = (shadow: ShadowRoot, css: string): void => {
|
|
15
|
+
if (
|
|
16
|
+
"adoptedStyleSheets" in Document.prototype &&
|
|
17
|
+
"replaceSync" in CSSStyleSheet.prototype
|
|
18
|
+
) {
|
|
19
|
+
const sheet = new CSSStyleSheet();
|
|
20
|
+
sheet.replaceSync(css);
|
|
21
|
+
shadow.adoptedStyleSheets = [sheet];
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const style = document.createElement("style");
|
|
26
|
+
style.textContent = css;
|
|
27
|
+
shadow.append(style);
|
|
28
|
+
};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineVikingElement,
|
|
3
|
+
HTMLElementBase,
|
|
4
|
+
readBooleanAttribute,
|
|
5
|
+
} from "../core/dom";
|
|
6
|
+
import { attachStyles, resetStyles } from "../core/styles";
|
|
7
|
+
|
|
8
|
+
const styles = `
|
|
9
|
+
${resetStyles}
|
|
10
|
+
|
|
11
|
+
:host {
|
|
12
|
+
display: contents;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
dialog {
|
|
16
|
+
width: min(calc(100vw - (var(--viking-space-2) * 2)), 42rem);
|
|
17
|
+
padding: 0;
|
|
18
|
+
border: 1px solid var(--viking-border-strong);
|
|
19
|
+
border-radius: var(--viking-radius-lg);
|
|
20
|
+
background: var(--viking-surface-recipe);
|
|
21
|
+
color: var(--viking-text);
|
|
22
|
+
box-shadow: var(--viking-shadow-lg);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
dialog::backdrop {
|
|
26
|
+
background: var(--viking-overlay-backdrop);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.modal {
|
|
30
|
+
display: grid;
|
|
31
|
+
gap: var(--viking-space-3);
|
|
32
|
+
padding: var(--viking-card-padding);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.header {
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: start;
|
|
38
|
+
justify-content: space-between;
|
|
39
|
+
gap: var(--viking-space-2);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.title {
|
|
43
|
+
margin: 0;
|
|
44
|
+
color: var(--viking-text);
|
|
45
|
+
font-size: var(--viking-font-size-lg);
|
|
46
|
+
line-height: var(--viking-line-height-tight);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.close {
|
|
50
|
+
display: inline-grid;
|
|
51
|
+
width: var(--viking-control-height-sm);
|
|
52
|
+
height: var(--viking-control-height-sm);
|
|
53
|
+
place-items: center;
|
|
54
|
+
border: 1px solid var(--viking-border);
|
|
55
|
+
border-radius: var(--viking-radius);
|
|
56
|
+
background: var(--viking-surface-alt);
|
|
57
|
+
color: var(--viking-text);
|
|
58
|
+
cursor: pointer;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.close:focus-visible {
|
|
62
|
+
outline: var(--viking-ring-width) solid var(--viking-ring);
|
|
63
|
+
outline-offset: var(--viking-ring-offset);
|
|
64
|
+
}
|
|
65
|
+
`;
|
|
66
|
+
|
|
67
|
+
export class VikingModal extends HTMLElementBase {
|
|
68
|
+
static readonly tagName = "viking-modal";
|
|
69
|
+
|
|
70
|
+
static get observedAttributes(): string[] {
|
|
71
|
+
return ["open", "label"];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private readonly shadowRootRef: ShadowRoot;
|
|
75
|
+
private dialog: HTMLDialogElement | null = null;
|
|
76
|
+
|
|
77
|
+
constructor() {
|
|
78
|
+
super();
|
|
79
|
+
this.shadowRootRef = this.attachShadow({ mode: "open" });
|
|
80
|
+
attachStyles(this.shadowRootRef, styles);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
connectedCallback(): void {
|
|
84
|
+
this.render();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
attributeChangedCallback(): void {
|
|
88
|
+
if (this.isConnected) {
|
|
89
|
+
this.syncOpenState();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
open(): void {
|
|
94
|
+
this.setAttribute("open", "");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
close(): void {
|
|
98
|
+
this.removeAttribute("open");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private render(): void {
|
|
102
|
+
const title = this.getAttribute("label") ?? "Dialog";
|
|
103
|
+
this.shadowRootRef.innerHTML = `
|
|
104
|
+
<dialog aria-label="${title}">
|
|
105
|
+
<section class="modal" part="surface">
|
|
106
|
+
<header class="header">
|
|
107
|
+
<h2 class="title"><slot name="title">${title}</slot></h2>
|
|
108
|
+
<button class="close" type="button" aria-label="Close dialog">x</button>
|
|
109
|
+
</header>
|
|
110
|
+
<slot></slot>
|
|
111
|
+
<slot name="footer"></slot>
|
|
112
|
+
</section>
|
|
113
|
+
</dialog>
|
|
114
|
+
`;
|
|
115
|
+
this.dialog = this.shadowRootRef.querySelector("dialog");
|
|
116
|
+
this.shadowRootRef
|
|
117
|
+
.querySelector(".close")
|
|
118
|
+
?.addEventListener("click", () => this.close());
|
|
119
|
+
this.dialog?.addEventListener("close", () => {
|
|
120
|
+
if (this.hasAttribute("open")) {
|
|
121
|
+
this.removeAttribute("open");
|
|
122
|
+
}
|
|
123
|
+
this.dispatchEvent(
|
|
124
|
+
new CustomEvent("viking-close", { bubbles: true, composed: true }),
|
|
125
|
+
);
|
|
126
|
+
});
|
|
127
|
+
this.syncOpenState();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private syncOpenState(): void {
|
|
131
|
+
if (!this.dialog) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (readBooleanAttribute(this, "open")) {
|
|
136
|
+
if (!this.dialog.open && typeof this.dialog.showModal === "function") {
|
|
137
|
+
this.dialog.showModal();
|
|
138
|
+
} else if (!this.dialog.open) {
|
|
139
|
+
this.dialog.setAttribute("open", "");
|
|
140
|
+
}
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (this.dialog.open && typeof this.dialog.close === "function") {
|
|
145
|
+
this.dialog.close();
|
|
146
|
+
} else {
|
|
147
|
+
this.dialog.removeAttribute("open");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export const registerVikingModal = (): void => {
|
|
153
|
+
defineVikingElement(VikingModal.tagName, VikingModal);
|
|
154
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./web/index";
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DEML branded icon paths — optimized SVG geometry (not sourced from Lucide).
|
|
3
|
+
* Use via viking-icon name="deml" | "deml-compact" | "deml-lockup".
|
|
4
|
+
*/
|
|
5
|
+
export const VIKING_BRAND_ICON_PATHS = {
|
|
6
|
+
/** Primary bar-chart mark in rounded frame (outline). */
|
|
7
|
+
deml: '<rect x="3" y="3" width="18" height="18" rx="2"/><path d="M8 17V13M12 17V8M16 17V11"/>',
|
|
8
|
+
/** Compact monogram for favicons and dense Drakkar shell. */
|
|
9
|
+
"deml-compact":
|
|
10
|
+
'<rect x="4" y="4" width="16" height="16" rx="3"/><path d="M9 16V12M12 16V9M15 16V13"/>',
|
|
11
|
+
/** Lockup mark with baseline accent bar. */
|
|
12
|
+
"deml-lockup":
|
|
13
|
+
'<rect x="3" y="3" width="18" height="14" rx="2"/><path d="M8 17V13M12 17V8M16 17V11"/><path d="M3 20h18"/>',
|
|
14
|
+
} as const;
|
|
15
|
+
|
|
16
|
+
/** Drakkar — Viking-UI / site shell brand marks (Lucide ship, build-time inlined). */
|
|
17
|
+
export const VIKING_DRAKKAR_ICON_PATHS = {
|
|
18
|
+
/** Primary Drakkar longship mark (outline). */
|
|
19
|
+
drakkar:
|
|
20
|
+
'<path d="M12 10.189V14"/><path d="M12 2v3"/><path d="M19 13V7a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v6"/><path d="M19.38 20A11.6 11.6 0 0 0 21 14l-8.188-3.639a2 2 0 0 0-1.624 0L3 14a11.6 11.6 0 0 0 2.81 7.76"/><path d="M2 21c.6.5 1.2 1 2.5 1 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1s1.2 1 2.5 1c2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"/>',
|
|
21
|
+
/** Compact tile for favicons and dense navbar chrome. */
|
|
22
|
+
"drakkar-compact":
|
|
23
|
+
'<rect x="3" y="3" width="18" height="18" rx="2"/><path d="M12 10.189V14"/><path d="M12 2v3"/><path d="M19 13V7a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v6"/><path d="M19.38 20A11.6 11.6 0 0 0 21 14l-8.188-3.639a2 2 0 0 0-1.624 0L3 14a11.6 11.6 0 0 0 2.81 7.76"/><path d="M2 21c.6.5 1.2 1 2.5 1 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1s1.2 1 2.5 1c2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"/>',
|
|
24
|
+
/** Lockup mark with baseline accent bar. */
|
|
25
|
+
"drakkar-lockup":
|
|
26
|
+
'<path d="M12 10.189V14"/><path d="M12 2v3"/><path d="M19 13V7a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v6"/><path d="M19.38 20A11.6 11.6 0 0 0 21 14l-8.188-3.639a2 2 0 0 0-1.624 0L3 14a11.6 11.6 0 0 0 2.81 7.76"/><path d="M2 21c.6.5 1.2 1 2.5 1 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1s1.2 1 2.5 1c2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"/><path d="M3 21h18"/>',
|
|
27
|
+
} as const;
|
|
28
|
+
|
|
29
|
+
/** Filled-path overrides for DEML brand marks. */
|
|
30
|
+
export const VIKING_BRAND_ICON_FILLED_PATHS: Partial<
|
|
31
|
+
Record<keyof typeof VIKING_BRAND_ICON_PATHS, string>
|
|
32
|
+
> = {
|
|
33
|
+
deml: '<path d="M5 4a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4zM8 13h2.5v4H8v-4zM12 8h2.5v9H12V8zM16 11h2.5v6H16v-6z"/>',
|
|
34
|
+
"deml-compact":
|
|
35
|
+
'<path d="M6 5a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V5zM9 12h1.5v4H9v-4zM12 9h1.5v7H12V9zM15 11h1.5v5H15v-5z"/>',
|
|
36
|
+
"deml-lockup":
|
|
37
|
+
'<path d="M4 4a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v11a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V4zM8 13h2.5v4H8v-4zM12 8h2.5v9H12V8zM16 11h2.5v6H16v-6z"/><rect x="3" y="19" width="18" height="2" rx="1"/>',
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/** Filled-path overrides for Drakkar brand marks. */
|
|
41
|
+
export const VIKING_DRAKKAR_ICON_FILLED_PATHS: Partial<
|
|
42
|
+
Record<keyof typeof VIKING_DRAKKAR_ICON_PATHS, string>
|
|
43
|
+
> = {
|
|
44
|
+
drakkar:
|
|
45
|
+
'<path d="M7 5h10a2 2 0 0 1 2 2v3.5L20.8 14.2l-7.8-3.5a1.8 1.8 0 0 0-1.4 0L3.2 14.2a10.5 10.5 0 0 0 2.6 7.2L5.2 13V7a2 2 0 0 0-2-2z"/><rect x="10.85" y="2" width="2.3" height="12" rx="0.4"/>',
|
|
46
|
+
"drakkar-compact":
|
|
47
|
+
'<path d="M3 3h18a2 2 0 0 1 2 2v18a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"/><path d="M7.5 12.5 12 9.8l4.5 2.7v2.2c0 .8-.5 1.4-1.2 1.7L12 17.8l-3.3-1.6c-.7-.3-1.2-.9-1.2-1.7v-2.2z"/><rect x="11" y="6" width="2" height="5.5" rx="0.35"/>',
|
|
48
|
+
"drakkar-lockup":
|
|
49
|
+
'<path d="M7 5h10a2 2 0 0 1 2 2v3.5L20.8 14.2l-7.8-3.5a1.8 1.8 0 0 0-1.4 0L3.2 14.2a10.5 10.5 0 0 0 2.6 7.2L5.2 13V7a2 2 0 0 0-2-2z"/><rect x="10.85" y="2" width="2.3" height="12" rx="0.4"/><rect x="3" y="20" width="18" height="2" rx="1"/>',
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export type VikingBrandIconName = keyof typeof VIKING_BRAND_ICON_PATHS;
|
|
53
|
+
|
|
54
|
+
export type VikingDrakkarIconName = keyof typeof VIKING_DRAKKAR_ICON_PATHS;
|
|
55
|
+
|
|
56
|
+
export const VIKING_BRAND_ICON_NAMES_LIST = Object.keys(
|
|
57
|
+
VIKING_BRAND_ICON_PATHS,
|
|
58
|
+
) as VikingBrandIconName[];
|
|
59
|
+
|
|
60
|
+
export const VIKING_DRAKKAR_ICON_NAMES_LIST = Object.keys(
|
|
61
|
+
VIKING_DRAKKAR_ICON_PATHS,
|
|
62
|
+
) as VikingDrakkarIconName[];
|