@govtechsg/sgds-web-component 0.0.8 → 0.0.10
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/.github/workflows/publish-latest.yml +22 -0
- package/.github/workflows/publish-pr.yml +28 -0
- package/.husky/commit-msg +4 -0
- package/.husky/prepare-commit-msg +8 -0
- package/.storybook/main.js +16 -0
- package/.storybook/preview-head.html +11 -0
- package/.storybook/preview.js +9 -0
- package/.vscode/settings.json +7 -0
- package/CONTRIBUTING.md +56 -0
- package/LICENSE +20 -0
- package/amplify.yml +22 -0
- package/commitlint.config.js +1 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/button-element.scss.html +112 -0
- package/coverage/lcov-report/button-element.ts.html +145 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +116 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov.info +32 -0
- package/index.html +430 -0
- package/{Button → lib/Button}/index.d.ts +0 -0
- package/{Button → lib/Button}/index.js +304 -39
- package/lib/Button/index.js.map +1 -0
- package/{Button → lib/Button}/package.json +0 -0
- package/lib/Button/sgds-button.d.ts +48 -0
- package/lib/Card/index.d.ts +1 -0
- package/lib/Card/index.js +6150 -0
- package/lib/Card/index.js.map +1 -0
- package/lib/Card/package.json +7 -0
- package/lib/Card/sgds-action-card.d.ts +20 -0
- package/lib/Checkbox/index.d.ts +1 -0
- package/lib/Checkbox/index.js +6366 -0
- package/lib/Checkbox/index.js.map +1 -0
- package/lib/Checkbox/package.json +7 -0
- package/lib/Checkbox/sgds-checkbox.d.ts +36 -0
- package/lib/Dropdown/index.d.ts +3 -0
- package/{Mainnav → lib/Dropdown}/index.js +2785 -9262
- package/lib/Dropdown/index.js.map +1 -0
- package/lib/Dropdown/package.json +7 -0
- package/lib/Dropdown/sgds-dropdown-item.d.ts +7 -0
- package/lib/Dropdown/sgds-dropdown.d.ts +7 -0
- package/{Footer → lib/Footer}/index.d.ts +0 -0
- package/{Footer → lib/Footer}/index.js +111 -95
- package/lib/Footer/index.js.map +1 -0
- package/{Footer → lib/Footer}/package.json +0 -0
- package/{Footer → lib/Footer}/sgds-footer.d.ts +2 -2
- package/lib/Input/index.d.ts +1 -0
- package/lib/Input/index.js +6656 -0
- package/lib/Input/index.js.map +1 -0
- package/lib/Input/package.json +7 -0
- package/lib/Input/sgds-input.d.ts +42 -0
- package/{Mainnav → lib/Mainnav}/index.d.ts +1 -0
- package/{index.js → lib/Mainnav/index.js} +3870 -23414
- package/lib/Mainnav/index.js.map +1 -0
- package/{Mainnav → lib/Mainnav}/package.json +0 -0
- package/lib/Mainnav/sgds-mainnav-dropdown.d.ts +5 -0
- package/lib/Mainnav/sgds-mainnav-item.d.ts +4 -0
- package/{Mainnav → lib/Mainnav}/sgds-mainnav.d.ts +2 -2
- package/{Masthead → lib/Masthead}/index.d.ts +0 -0
- package/{Masthead → lib/Masthead}/index.js +140 -114
- package/lib/Masthead/index.js.map +1 -0
- package/{Masthead → lib/Masthead}/package.json +0 -0
- package/{Masthead → lib/Masthead}/sgds-masthead.d.ts +1 -1
- package/lib/Modal/index.d.ts +1 -0
- package/lib/Modal/index.js +6432 -0
- package/lib/Modal/index.js.map +1 -0
- package/lib/Modal/package.json +7 -0
- package/lib/Modal/sgds-modal.d.ts +28 -0
- package/lib/QuantityToggle/index.d.ts +1 -0
- package/lib/QuantityToggle/index.js +7049 -0
- package/lib/QuantityToggle/index.js.map +1 -0
- package/lib/QuantityToggle/package.json +7 -0
- package/lib/QuantityToggle/sgds-quantitytoggle.d.ts +30 -0
- package/lib/Radio/index.d.ts +2 -0
- package/lib/Radio/index.js +12607 -0
- package/lib/Radio/index.js.map +1 -0
- package/lib/Radio/package.json +7 -0
- package/lib/Radio/sgds-radio.d.ts +31 -0
- package/lib/Radio/sgds-radiogroup.d.ts +41 -0
- package/{Sidenav → lib/Sidenav}/index.d.ts +0 -0
- package/{Sidenav → lib/Sidenav}/index.js +2266 -2171
- package/lib/Sidenav/index.js.map +1 -0
- package/{Sidenav → lib/Sidenav}/package.json +0 -0
- package/{Sidenav → lib/Sidenav}/sgds-sidenav-item.d.ts +2 -1
- package/lib/Sidenav/sgds-sidenav-link.d.ts +4 -0
- package/{Sidenav → lib/Sidenav}/sgds-sidenav.d.ts +1 -1
- package/lib/Tab/index.d.ts +3 -0
- package/lib/Tab/index.js +13557 -0
- package/lib/Tab/index.js.map +1 -0
- package/lib/Tab/package.json +7 -0
- package/lib/Tab/sgds-tab.d.ts +26 -0
- package/lib/Tab/sgds-tabgroup.d.ts +47 -0
- package/lib/Tab/sgds-tabpanel.d.ts +25 -0
- package/lib/Textarea/index.d.ts +1 -0
- package/lib/Textarea/index.js +6696 -0
- package/lib/Textarea/index.js.map +1 -0
- package/lib/Textarea/package.json +7 -0
- package/lib/Textarea/sgds-textarea.d.ts +53 -0
- package/lib/index.d.ts +16 -0
- package/lib/index.js +134580 -0
- package/lib/index.js.map +1 -0
- package/lib/umd/index.js +134587 -0
- package/lib/umd/index.js.map +1 -0
- package/lib/utils/animate.d.ts +10 -0
- package/lib/utils/animation-registry.d.ts +18 -0
- package/{utils → lib/utils}/breakpoints.d.ts +0 -0
- package/lib/utils/card-element.d.ts +11 -0
- package/lib/utils/defaultvalue.d.ts +2 -0
- package/lib/utils/dropdown-element.d.ts +37 -0
- package/lib/utils/event.d.ts +2 -0
- package/lib/utils/form.d.ts +38 -0
- package/{utils → lib/utils}/generateId.d.ts +0 -0
- package/lib/utils/link-element.d.ts +7 -0
- package/lib/utils/mergeDeep.d.ts +2 -0
- package/lib/utils/modal.d.ts +12 -0
- package/lib/utils/object.d.ts +2 -0
- package/lib/utils/offset.d.ts +4 -0
- package/lib/utils/scroll.d.ts +13 -0
- package/{utils → lib/utils}/sgds-element.d.ts +0 -0
- package/lib/utils/slot.d.ts +22 -0
- package/lib/utils/tabbable.d.ts +8 -0
- package/lib/utils/watch.d.ts +14 -0
- package/mocks/dropdown.d.ts +4 -0
- package/mocks/dropdown.ts +27 -0
- package/mocks/link.d.ts +3 -0
- package/mocks/link.ts +6 -0
- package/package.json +65 -10
- package/rollup.config.js +73 -0
- package/rollup.test.config.js +42 -0
- package/scripts/buildUtils.js +30 -0
- package/scripts/frankBuild.js +49 -0
- package/src/Button/index.ts +1 -0
- package/src/Button/sgds-button.scss +28 -0
- package/src/Button/sgds-button.ts +153 -0
- package/src/Card/index.ts +1 -0
- package/src/Card/sgds-action-card.scss +27 -0
- package/src/Card/sgds-action-card.ts +115 -0
- package/src/Checkbox/index.ts +1 -0
- package/src/Checkbox/sgds-checkbox.scss +4 -0
- package/src/Checkbox/sgds-checkbox.ts +149 -0
- package/src/Dropdown/index.ts +3 -0
- package/src/Dropdown/sgds-dropdown-item.ts +39 -0
- package/src/Dropdown/sgds-dropdown.scss +5 -0
- package/src/Dropdown/sgds-dropdown.ts +54 -0
- package/src/Footer/index.ts +3 -0
- package/src/Footer/sgds-footer.scss +5 -0
- package/src/Footer/sgds-footer.ts +121 -0
- package/src/Input/index.ts +1 -0
- package/src/Input/sgds-input.scss +20 -0
- package/src/Input/sgds-input.ts +178 -0
- package/src/Mainnav/index.ts +4 -0
- package/src/Mainnav/sgds-mainnav-dropdown.scss +13 -0
- package/src/Mainnav/sgds-mainnav-dropdown.ts +45 -0
- package/src/Mainnav/sgds-mainnav-item.scss +24 -0
- package/src/Mainnav/sgds-mainnav-item.ts +8 -0
- package/src/Mainnav/sgds-mainnav.scss +39 -0
- package/src/Mainnav/sgds-mainnav.ts +183 -0
- package/src/Masthead/index.ts +1 -0
- package/src/Masthead/sgds-masthead.scss +217 -0
- package/src/Masthead/sgds-masthead.ts +189 -0
- package/src/Modal/index.ts +1 -0
- package/src/Modal/sgds-modal.scss +128 -0
- package/src/Modal/sgds-modal.ts +309 -0
- package/src/QuantityToggle/index.ts +1 -0
- package/src/QuantityToggle/sgds-quantitytoggle.scss +10 -0
- package/src/QuantityToggle/sgds-quantitytoggle.ts +130 -0
- package/src/Radio/index.ts +2 -0
- package/src/Radio/sgds-radio.scss +5 -0
- package/src/Radio/sgds-radio.ts +120 -0
- package/src/Radio/sgds-radiogroup.scss +22 -0
- package/src/Radio/sgds-radiogroup.ts +221 -0
- package/src/Sidenav/index.ts +4 -0
- package/src/Sidenav/sgds-sidenav-item.scss +73 -0
- package/src/Sidenav/sgds-sidenav-item.ts +145 -0
- package/src/Sidenav/sgds-sidenav-link.scss +25 -0
- package/src/Sidenav/sgds-sidenav-link.ts +8 -0
- package/src/Sidenav/sgds-sidenav.scss +6 -0
- package/src/Sidenav/sgds-sidenav.ts +33 -0
- package/src/Tab/index.ts +3 -0
- package/src/Tab/sgds-tab.scss +84 -0
- package/src/Tab/sgds-tab.ts +87 -0
- package/src/Tab/sgds-tabgroup.scss +198 -0
- package/src/Tab/sgds-tabgroup.ts +295 -0
- package/src/Tab/sgds-tabpanel.scss +12 -0
- package/src/Tab/sgds-tabpanel.ts +55 -0
- package/src/Textarea/index.ts +1 -0
- package/src/Textarea/sgds-textarea.scss +23 -0
- package/src/Textarea/sgds-textarea.ts +201 -0
- package/src/index.ts +16 -0
- package/src/utils/animate.ts +69 -0
- package/src/utils/animation-registry.ts +71 -0
- package/src/utils/base.scss +14 -0
- package/src/utils/breakpoints.ts +5 -0
- package/src/utils/card-element.ts +42 -0
- package/src/utils/components.style.scss +531 -0
- package/src/utils/defaultvalue.ts +51 -0
- package/src/utils/dropdown-element.ts +244 -0
- package/src/utils/event.ts +13 -0
- package/src/utils/form.ts +183 -0
- package/src/utils/generateId.ts +4 -0
- package/src/utils/link-element.ts +34 -0
- package/src/utils/mergeDeep.ts +22 -0
- package/src/utils/modal.ts +64 -0
- package/src/utils/object.ts +2 -0
- package/src/utils/offset.ts +6 -0
- package/src/utils/scroll.ts +57 -0
- package/src/utils/sgds-element.ts +18 -0
- package/src/utils/slot.ts +102 -0
- package/src/utils/tabbable.ts +81 -0
- package/src/utils/watch.ts +62 -0
- package/stories/ActionCard.stories.mdx +199 -0
- package/stories/Button.stories.mdx +194 -0
- package/stories/Checkbox.stories.mdx +196 -0
- package/stories/Dropdown.stories.mdx +152 -0
- package/stories/Footer.stories.mdx +261 -0
- package/stories/Input.stories.mdx +236 -0
- package/stories/MainNav.stories.mdx +169 -0
- package/stories/Masthead.stories.mdx +112 -0
- package/stories/Modal.stories.mdx +103 -0
- package/stories/QuantityToggle.stories.mdx +97 -0
- package/stories/Radio.stories.mdx +262 -0
- package/stories/Sample.stories.js +29 -0
- package/stories/Sample.stories.mdx +33 -0
- package/stories/SideNav.stories.mdx +245 -0
- package/stories/common.js +185 -0
- package/stories/textarea.stories.mdx +253 -0
- package/test/button.element.test.ts +185 -0
- package/test/checkbox.test.ts +240 -0
- package/test/dropdown.test.ts +637 -0
- package/test/footer.test.ts +181 -0
- package/test/generateId.test.ts +18 -0
- package/test/input.element.test.ts +316 -0
- package/test/link-element.test.ts +38 -0
- package/test/mainnav.test.ts +313 -0
- package/test/masthead.test.ts +116 -0
- package/test/modal.test.ts +149 -0
- package/test/quantitytoggle.test.ts +76 -0
- package/test/radio.test.ts +310 -0
- package/test/selectable-card.test.ts +159 -0
- package/test/sidenav.test.ts +390 -0
- package/test/tab.test.ts +76 -0
- package/test/textarea.test.ts +126 -0
- package/tsconfig.json +26 -0
- package/tsconfig.test.json +24 -0
- package/typings/scss.d.ts +5 -0
- package/web-dev-server.config.mjs +7 -0
- package/web-test-runner.config.mjs +47 -0
- package/Button/index.js.map +0 -1
- package/Button/sgds-button.d.ts +0 -23
- package/Footer/index.js.map +0 -1
- package/Mainnav/index.js.map +0 -1
- package/Mainnav/sgds-mainnav-item.d.ts +0 -7
- package/Masthead/index.js.map +0 -1
- package/Sidenav/index.js.map +0 -1
- package/Sidenav/sgds-sidenav-link.d.ts +0 -7
- package/index.d.ts +0 -5
- package/index.js.map +0 -1
- package/umd/index.js +0 -52097
- package/umd/index.js.map +0 -1
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { customElement, property, state, query} from "lit/decorators.js";
|
|
2
|
+
import { html, literal } from 'lit/static-html.js';
|
|
3
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
4
|
+
import {classMap} from 'lit/directives/class-map.js';
|
|
5
|
+
import { FormSubmitController } from "../utils/form";
|
|
6
|
+
import SgdsElement from "../utils/sgds-element";
|
|
7
|
+
import styles from "./sgds-button.scss";
|
|
8
|
+
|
|
9
|
+
export type ButtonVariant =
|
|
10
|
+
"primary" | "secondary" | "success" | "danger" | "warning" | "info" | "light" | "dark" | "link" | "icon" |
|
|
11
|
+
"outline-primary" | "outline-secondary" | "outline-success" | "outline-danger" | "outline-warning" | "outline-info" | "outline-light" | "outline-dark"
|
|
12
|
+
|
|
13
|
+
@customElement("sgds-button")
|
|
14
|
+
export class SgdsButton extends SgdsElement {
|
|
15
|
+
static styles = styles;
|
|
16
|
+
|
|
17
|
+
@query('.btn') button: HTMLButtonElement | HTMLLinkElement;
|
|
18
|
+
|
|
19
|
+
private readonly formSubmitController = new FormSubmitController(this, {
|
|
20
|
+
form: (input: HTMLInputElement) => {
|
|
21
|
+
// Buttons support a form attribute that points to an arbitrary form, so if this attribute it set we need to query
|
|
22
|
+
// the form from the same root using its id
|
|
23
|
+
if (input.hasAttribute('form')) {
|
|
24
|
+
const doc = input.getRootNode() as Document | ShadowRoot;
|
|
25
|
+
const formId = input.getAttribute('form')!;
|
|
26
|
+
return doc.getElementById(formId) as HTMLFormElement;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Fall back to the closest containing form
|
|
30
|
+
return input.closest('form');
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
@state() private hasFocus = false;
|
|
35
|
+
|
|
36
|
+
/** The button's variant. */
|
|
37
|
+
@property({ reflect: true }) variant: ButtonVariant = "primary";
|
|
38
|
+
|
|
39
|
+
@property({ reflect: true }) buttonClasses? : string;
|
|
40
|
+
|
|
41
|
+
/** Button sizes */
|
|
42
|
+
@property({ reflect: true }) size : 'sm' | 'lg' ;
|
|
43
|
+
|
|
44
|
+
/** Button active state */
|
|
45
|
+
@property({ type: Boolean, reflect: true }) active = false ;
|
|
46
|
+
|
|
47
|
+
/** Button disabled state */
|
|
48
|
+
@property({ type: Boolean, reflect: true }) disabled = false ;
|
|
49
|
+
|
|
50
|
+
@property() type: 'button' | 'submit' | 'reset' = 'button' ;
|
|
51
|
+
|
|
52
|
+
/** When set, the underlying button will be rendered as an `<a>` with this `href` instead of a `<button>`. */
|
|
53
|
+
@property() href?: string;
|
|
54
|
+
|
|
55
|
+
/** Tells the browser where to open the link. Only used when `href` is set. */
|
|
56
|
+
@property() target?: '_blank' | '_parent' | '_self' | '_top';
|
|
57
|
+
|
|
58
|
+
/** Tells the browser to download the linked file as this filename. Only used when `href` is set. */
|
|
59
|
+
@property({ reflect: true }) download?: string;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The "form owner" to associate the button with. If omitted, the closest containing form will be used instead. The
|
|
63
|
+
* value of this attribute must be an id of a form in the same document or shadow root as the button.
|
|
64
|
+
*/
|
|
65
|
+
@property() form: string;
|
|
66
|
+
|
|
67
|
+
/** Used to override the form owner's `action` attribute. */
|
|
68
|
+
@property({ attribute: 'formaction' }) formAction: string;
|
|
69
|
+
|
|
70
|
+
/** Used to override the form owner's `method` attribute. */
|
|
71
|
+
@property({ attribute: 'formmethod' }) formMethod: 'post' | 'get';
|
|
72
|
+
|
|
73
|
+
/** Used to override the form owner's `novalidate` attribute. */
|
|
74
|
+
@property({ attribute: 'formnovalidate', type: Boolean }) formNoValidate: boolean;
|
|
75
|
+
|
|
76
|
+
/** Used to override the form owner's `target` attribute. */
|
|
77
|
+
@property({ attribute: 'formtarget' }) formTarget: '_self' | '_blank' | '_parent' | '_top' | string;
|
|
78
|
+
|
|
79
|
+
/** Sets focus on the button. */
|
|
80
|
+
focus(options?: FocusOptions) {
|
|
81
|
+
this.button.focus(options);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Simulates a click on the button. */
|
|
85
|
+
click() {
|
|
86
|
+
this.button.click();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Removes focus from the button. */
|
|
90
|
+
blur() {
|
|
91
|
+
this.button.blur();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
handleBlur() {
|
|
95
|
+
this.hasFocus = false;
|
|
96
|
+
this.emit('sgds-blur');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
handleFocus() {
|
|
100
|
+
this.hasFocus = true;
|
|
101
|
+
this.emit('sgds-focus');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
handleClick(event: MouseEvent) {
|
|
105
|
+
if (this.disabled) {
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
event.stopPropagation();
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (this.type === 'submit') {
|
|
112
|
+
this.formSubmitController.submit(this);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (this.type === 'reset') {
|
|
116
|
+
this.formSubmitController.reset(this);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
render() {
|
|
121
|
+
const isLink = this.href;
|
|
122
|
+
const tag = isLink ? literal`a` : literal`button`;
|
|
123
|
+
return html`
|
|
124
|
+
<${tag}
|
|
125
|
+
class="sgds btn ${classMap(
|
|
126
|
+
{
|
|
127
|
+
'disabled': isLink && this.disabled,
|
|
128
|
+
'active': this.active,
|
|
129
|
+
[`btn-${this.variant}`]: this.variant,
|
|
130
|
+
[`btn-${this.size}`]: this.size,
|
|
131
|
+
[`${this.buttonClasses}`]: this.buttonClasses
|
|
132
|
+
}
|
|
133
|
+
)}"
|
|
134
|
+
?disabled=${ifDefined(isLink ? undefined : this.disabled)}
|
|
135
|
+
type=${ifDefined(isLink ? undefined : this.type)}
|
|
136
|
+
href=${ifDefined(isLink ? this.href : undefined)}
|
|
137
|
+
target=${ifDefined(isLink ? this.target : undefined)}
|
|
138
|
+
download=${ifDefined(isLink ? this.download : undefined)}
|
|
139
|
+
rel=${ifDefined(isLink && this.target === "_blank" ? 'noreferrer noopener' : undefined)}
|
|
140
|
+
role=${ifDefined(isLink ? 'button': undefined )}
|
|
141
|
+
aria-disabled=${this.disabled ? 'true' : 'false'}
|
|
142
|
+
tabindex=${this.disabled ? '-1' : '0'}
|
|
143
|
+
@click=${this.handleClick}
|
|
144
|
+
@focus=${this.handleFocus}
|
|
145
|
+
@blur=${this.handleBlur}
|
|
146
|
+
>
|
|
147
|
+
<slot></slot>
|
|
148
|
+
</${tag}>
|
|
149
|
+
`;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export default SgdsButton;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SgdsActionCard } from "./sgds-action-card";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
@import "../utils/base.scss";
|
|
2
|
+
@import "~@govtechsg/sgds/sass/card/";
|
|
3
|
+
|
|
4
|
+
:host {
|
|
5
|
+
.sgds {
|
|
6
|
+
&.card {
|
|
7
|
+
&[variant*="card-action"] {
|
|
8
|
+
.card-body {
|
|
9
|
+
sl-icon {
|
|
10
|
+
font-size: 1.5rem;
|
|
11
|
+
margin-right: 1rem;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
@each $color, $value in $theme-colors {
|
|
17
|
+
&.text-#{$color} {
|
|
18
|
+
color: $value !important;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
@each $color, $value in $theme-colors {
|
|
22
|
+
&.bg-#{$color} {
|
|
23
|
+
background-color: $value !important;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { customElement, property, state, query } from "lit/decorators.js";
|
|
2
|
+
import { html, literal } from "lit/static-html.js";
|
|
3
|
+
import { classMap } from "lit/directives/class-map.js";
|
|
4
|
+
import styles from "./sgds-action-card.scss";
|
|
5
|
+
import { CardElement } from "../utils/card-element";
|
|
6
|
+
import { ref, createRef, Ref } from "lit/directives/ref.js";
|
|
7
|
+
|
|
8
|
+
export type CardVariant = "card-action" | "card-action-quantity-toggle";
|
|
9
|
+
|
|
10
|
+
export type TypeVariant = "checkbox" | "radio";
|
|
11
|
+
|
|
12
|
+
@customElement("sgds-action-card")
|
|
13
|
+
export class SgdsActionCard extends CardElement {
|
|
14
|
+
static styles = styles;
|
|
15
|
+
|
|
16
|
+
// @query("sgds-checkbox") // Define the query
|
|
17
|
+
// inputEl!: HTMLInputElement; // Declare the prop
|
|
18
|
+
|
|
19
|
+
inputRef: Ref<HTMLInputElement> = createRef();
|
|
20
|
+
|
|
21
|
+
@property({ type: String, reflect: true }) type?: TypeVariant = "checkbox";
|
|
22
|
+
|
|
23
|
+
/** Use on actionable cards like SelectableCard and Quantity Toggle Card' */
|
|
24
|
+
@property({ reflect: true }) variant?: CardVariant = "card-action";
|
|
25
|
+
|
|
26
|
+
/** The card's subtitle iconName. */
|
|
27
|
+
@property({ reflect: true }) iconName?: string;
|
|
28
|
+
|
|
29
|
+
/** The input's id. */
|
|
30
|
+
@property({ reflect: true }) inputId?: string;
|
|
31
|
+
|
|
32
|
+
@property({ reflect: true, type: Boolean })
|
|
33
|
+
active = false;
|
|
34
|
+
|
|
35
|
+
// Declare the click event listener
|
|
36
|
+
onInputChange() {
|
|
37
|
+
this.inputRef.value.click();
|
|
38
|
+
if (this.inputRef.value.checked && (!this.inputRef.value.disabled)) this.active = true;
|
|
39
|
+
else if (!this.inputRef.value.checked) {
|
|
40
|
+
this.active = false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
handleKeyDown(event: KeyboardEvent) {
|
|
45
|
+
const hasModifier =
|
|
46
|
+
event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;
|
|
47
|
+
if (event.key === "Enter" && !hasModifier) {
|
|
48
|
+
this.onInputChange();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// handleChange(event: string){
|
|
52
|
+
// this.checked = this.inputRef.value.checked;
|
|
53
|
+
// this.emit(event);
|
|
54
|
+
// }
|
|
55
|
+
|
|
56
|
+
render() {
|
|
57
|
+
const checkbox = html`<sgds-checkbox
|
|
58
|
+
${ref(this.inputRef)}
|
|
59
|
+
?disabled=${this.disabled}
|
|
60
|
+
checkboxId=${this.inputId}
|
|
61
|
+
@click=${this.onInputChange}
|
|
62
|
+
@keydown=${this.handleKeyDown}
|
|
63
|
+
></sgds-checkbox>`;
|
|
64
|
+
|
|
65
|
+
const radio = html`<sgds-radio
|
|
66
|
+
${ref(this.inputRef)}
|
|
67
|
+
?disabled=${this.disabled}
|
|
68
|
+
radioId=${this.inputId}
|
|
69
|
+
@click=${this.onInputChange}
|
|
70
|
+
@keydown=${this.handleKeyDown}
|
|
71
|
+
></sgds-radio>`;
|
|
72
|
+
|
|
73
|
+
const icon = html`<sl-icon name="${this.iconName}"></sl-icon>`;
|
|
74
|
+
|
|
75
|
+
return html`
|
|
76
|
+
<div
|
|
77
|
+
tabindex=${this.disabled ? "-1" : "0"}
|
|
78
|
+
@click=${this.onInputChange}
|
|
79
|
+
@keydown=${this.handleKeyDown}
|
|
80
|
+
|
|
81
|
+
variant="card-action"
|
|
82
|
+
class="sgds card
|
|
83
|
+
${classMap({
|
|
84
|
+
[`text-${this.textColor}`]: this.textColor,
|
|
85
|
+
[`bg-${this.bgColor}`]: this.bgColor,
|
|
86
|
+
[`border-${this.borderColor}`]: this.borderColor,
|
|
87
|
+
["is-active"]: this.active,
|
|
88
|
+
})}
|
|
89
|
+
"
|
|
90
|
+
>
|
|
91
|
+
<div class="card-body">
|
|
92
|
+
<h6 class="text-muted card-subtitle">
|
|
93
|
+
<div>
|
|
94
|
+
${this.iconName == undefined ? undefined : icon}
|
|
95
|
+
<slot name="card-subtitle"></slot></slot>
|
|
96
|
+
</div>
|
|
97
|
+
<div class="card-input">
|
|
98
|
+
${
|
|
99
|
+
this.type == "checkbox" && this.variant == "card-action"
|
|
100
|
+
? checkbox
|
|
101
|
+
: this.type == "radio" && this.variant == "card-action"
|
|
102
|
+
? radio
|
|
103
|
+
: undefined
|
|
104
|
+
}
|
|
105
|
+
</div>
|
|
106
|
+
</h6>
|
|
107
|
+
<h5 class="card-title"><slot name="card-title"></slot></h5>
|
|
108
|
+
<p class="card-text"><slot name="card-text"></slot></p>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export default SgdsActionCard;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {SgdsCheckbox} from './sgds-checkbox';
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { LitElement, html } from "lit";
|
|
2
|
+
import { customElement, property, query, state } from "lit/decorators.js";
|
|
3
|
+
import { live } from "lit/directives/live.js";
|
|
4
|
+
import styles from "./sgds-checkbox.scss";
|
|
5
|
+
import { ifDefined } from "lit/directives/if-defined.js";
|
|
6
|
+
import SgdsElement from "../utils/sgds-element";
|
|
7
|
+
import { classMap } from "lit/directives/class-map.js";
|
|
8
|
+
import genId from "../utils/generateId";
|
|
9
|
+
import { defaultValue } from "../utils/defaultvalue";
|
|
10
|
+
import { FormSubmitController } from "../utils/form";
|
|
11
|
+
import { watch } from "../utils/watch";
|
|
12
|
+
|
|
13
|
+
@customElement("sgds-checkbox")
|
|
14
|
+
export class SgdsCheckbox extends SgdsElement {
|
|
15
|
+
static styles = styles;
|
|
16
|
+
|
|
17
|
+
@query('input[type="checkbox"]') input: HTMLInputElement;
|
|
18
|
+
|
|
19
|
+
private readonly formSubmitController = new FormSubmitController(this, {
|
|
20
|
+
value: (control: SgdsCheckbox) =>
|
|
21
|
+
control.checked ? control.value : undefined,
|
|
22
|
+
defaultValue: (control: SgdsCheckbox) => control.defaultChecked,
|
|
23
|
+
setValue: (control: SgdsCheckbox, checked: boolean) =>
|
|
24
|
+
(control.checked = checked),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
/** Name of the HTML form control. Submitted with the form as part of a name/value pair. */
|
|
28
|
+
@property({reflect: true }) name: string;
|
|
29
|
+
|
|
30
|
+
/** For Id/For pair of the HTML form control. */
|
|
31
|
+
@property({ type: String, reflect: true }) checkboxId = genId("checkbox");
|
|
32
|
+
|
|
33
|
+
/** For aria-label when there is no appropriate text label visible */
|
|
34
|
+
@property({ type: String, reflect: true }) ariaLabel = "checkbox";
|
|
35
|
+
|
|
36
|
+
/** Manually style the input as valid */
|
|
37
|
+
@property({ type: Boolean, reflect: true }) valid = false;
|
|
38
|
+
|
|
39
|
+
/** Manually style the input as invalid */
|
|
40
|
+
@property({ type: Boolean, reflect: true }) invalid = false;
|
|
41
|
+
|
|
42
|
+
/** Value of the HTML form control. Primarily used to differentiate a list of related checkboxes that have the same name. */
|
|
43
|
+
@property() value: string;
|
|
44
|
+
|
|
45
|
+
/** Makes the checkbox a required field. */
|
|
46
|
+
@property({ type: Boolean, reflect: true }) required = false;
|
|
47
|
+
|
|
48
|
+
/** Draws the checkbox in a checked state. */
|
|
49
|
+
@property({ type: Boolean, reflect: true }) checked = false;
|
|
50
|
+
|
|
51
|
+
/** Disables the checkbox (so the user can't check / uncheck it). */
|
|
52
|
+
@property({ type: Boolean, reflect: true }) disabled = false;
|
|
53
|
+
|
|
54
|
+
/** Gets or sets the default value used to reset this element. The initial value corresponds to the one originally specified in the HTML that created this element. */
|
|
55
|
+
@defaultValue("checked")
|
|
56
|
+
defaultChecked = false;
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
/** Simulates a click on the checkbox. */
|
|
60
|
+
click() {
|
|
61
|
+
this.input.click();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Checks for validity and shows the browser's validation message if the control is invalid. */
|
|
65
|
+
reportValidity() {
|
|
66
|
+
if (!this.input.reportValidity()) {
|
|
67
|
+
this.invalid = !this.input.checkValidity();
|
|
68
|
+
}
|
|
69
|
+
return this.input.reportValidity();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
handleChange() {
|
|
73
|
+
// console.log(
|
|
74
|
+
// "when this.click() is fired, input detects a change --> handleChange runs"
|
|
75
|
+
// );
|
|
76
|
+
this.checked = !this.checked;
|
|
77
|
+
this.value = this.input.value;
|
|
78
|
+
this.emit("sgds-change");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
handleKeyDown(event: KeyboardEvent) {
|
|
82
|
+
const hasModifier =
|
|
83
|
+
event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;
|
|
84
|
+
if (event.key === "Enter" && !hasModifier) {
|
|
85
|
+
// console.log(
|
|
86
|
+
// "so here we are trying to mimick keydown enter event like a mousclick event"
|
|
87
|
+
// );
|
|
88
|
+
this.click();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@watch("disabled", { waitUntilFirstUpdate: true })
|
|
93
|
+
handleDisabledChange() {
|
|
94
|
+
// Disabled form controls are always valid, so we need to recheck validity when the state changes
|
|
95
|
+
this.input.disabled = this.disabled;
|
|
96
|
+
this.invalid = !this.input.checkValidity();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@watch("checked", { waitUntilFirstUpdate: true })
|
|
100
|
+
handleStateChange() {
|
|
101
|
+
this.invalid = !this.input.checkValidity();
|
|
102
|
+
if (this.required) this.valid = this.input.checkValidity();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
render() {
|
|
106
|
+
return html`
|
|
107
|
+
<div part="base" class="form-check">
|
|
108
|
+
<input
|
|
109
|
+
part="control"
|
|
110
|
+
class=${classMap({
|
|
111
|
+
"form-check-input": true,
|
|
112
|
+
"is-invalid": this.invalid,
|
|
113
|
+
"is-valid": this.valid,
|
|
114
|
+
})}
|
|
115
|
+
type="checkbox"
|
|
116
|
+
id=${ifDefined(this.checkboxId)}
|
|
117
|
+
aria-invalid=${this.invalid ? "true" : "false"}
|
|
118
|
+
name=${ifDefined(this.name)}
|
|
119
|
+
value=${ifDefined(this.value)}
|
|
120
|
+
.checked=${live(this.checked)}
|
|
121
|
+
?disabled=${this.disabled}
|
|
122
|
+
?required=${this.required}
|
|
123
|
+
aria-disabled=${this.disabled ? "true" : "false"}
|
|
124
|
+
aria-checked=${this.checked ? "true" : "false"}
|
|
125
|
+
@change=${this.handleChange}
|
|
126
|
+
@keydown=${this.handleKeyDown}
|
|
127
|
+
/>
|
|
128
|
+
<label
|
|
129
|
+
part="label"
|
|
130
|
+
for="${ifDefined(this.checkboxId)}"
|
|
131
|
+
aria-label=${ifDefined(this.ariaLabel)}
|
|
132
|
+
class="form-check-label"
|
|
133
|
+
><slot></slot
|
|
134
|
+
></label>
|
|
135
|
+
${this.invalid
|
|
136
|
+
? html`<slot
|
|
137
|
+
name="feedback"
|
|
138
|
+
part="feedback"
|
|
139
|
+
class=${classMap({
|
|
140
|
+
"invalid-feedback": true,
|
|
141
|
+
})}
|
|
142
|
+
></slot>`
|
|
143
|
+
: undefined}
|
|
144
|
+
</div>
|
|
145
|
+
`;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export default SgdsCheckbox;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { html } from "lit";
|
|
2
|
+
import { customElement, property, query } from "lit/decorators.js";
|
|
3
|
+
import LinkElement from "../utils/link-element";
|
|
4
|
+
import styles from "./sgds-dropdown.scss";
|
|
5
|
+
import {classMap} from 'lit/directives/class-map.js';
|
|
6
|
+
|
|
7
|
+
@customElement("sgds-dropdown-item")
|
|
8
|
+
export class SgdsDropdownItem extends LinkElement {
|
|
9
|
+
static styles = styles
|
|
10
|
+
|
|
11
|
+
@query('a')
|
|
12
|
+
anchor: HTMLElement
|
|
13
|
+
firstUpdated(){
|
|
14
|
+
//required when navigate with ArrowDown/ArrowUp
|
|
15
|
+
this.addEventListener('keydown', (e:KeyboardEvent) => {
|
|
16
|
+
if (e.key === 'Enter') {
|
|
17
|
+
this.anchor.click()
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
render() {
|
|
23
|
+
return html`
|
|
24
|
+
<li>
|
|
25
|
+
<a
|
|
26
|
+
href="${this.href}"
|
|
27
|
+
class="dropdown-item ${classMap({
|
|
28
|
+
'disabled': this.disabled,
|
|
29
|
+
'active': this.active
|
|
30
|
+
})}"
|
|
31
|
+
?disabled=${this.disabled}
|
|
32
|
+
aria-disabled=${this.disabled ? 'true' : 'false'}
|
|
33
|
+
tabindex=${this.disabled ? '-1': '0'}
|
|
34
|
+
><slot></slot
|
|
35
|
+
></a>
|
|
36
|
+
</li>
|
|
37
|
+
`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { html } from "lit";
|
|
2
|
+
import { customElement } from "lit/decorators.js";
|
|
3
|
+
import { ref } from "lit/directives/ref.js";
|
|
4
|
+
import styles from "./sgds-dropdown.scss";
|
|
5
|
+
import { DropdownElement } from "../utils/dropdown-element";
|
|
6
|
+
|
|
7
|
+
export type DropDirection = "left" | "right" | "up" | "down";
|
|
8
|
+
@customElement("sgds-dropdown")
|
|
9
|
+
export class SgdsDropdown extends DropdownElement {
|
|
10
|
+
static styles = styles;
|
|
11
|
+
constructor(){
|
|
12
|
+
super()
|
|
13
|
+
this.modifierOpt = [
|
|
14
|
+
{
|
|
15
|
+
name: "offset",
|
|
16
|
+
options: {
|
|
17
|
+
offset: [0, 10],
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
render() {
|
|
23
|
+
return html`
|
|
24
|
+
<div>
|
|
25
|
+
<sgds-button
|
|
26
|
+
variant="outline-${this.variant}"
|
|
27
|
+
?disabled=${this.disabled}
|
|
28
|
+
aria-expanded="${this.menuIsOpen}"
|
|
29
|
+
${ref(this.myDropdown)}
|
|
30
|
+
@click=${() => this._onClickButton()}
|
|
31
|
+
id=${this.togglerId}
|
|
32
|
+
>
|
|
33
|
+
${this.togglerText}
|
|
34
|
+
<svg
|
|
35
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
36
|
+
width="16"
|
|
37
|
+
height="16"
|
|
38
|
+
fill="currentColor"
|
|
39
|
+
class="bi bi-chevron-down"
|
|
40
|
+
viewBox="0 0 16 16"
|
|
41
|
+
>
|
|
42
|
+
<path
|
|
43
|
+
fill-rule="evenodd"
|
|
44
|
+
d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z"
|
|
45
|
+
/>
|
|
46
|
+
</svg>
|
|
47
|
+
</sgds-button>
|
|
48
|
+
<ul class="dropdown-menu" role="menu" part="menu">
|
|
49
|
+
<slot @click=${this._handleSelectSlot}></slot>
|
|
50
|
+
</ul>
|
|
51
|
+
</div>
|
|
52
|
+
`;
|
|
53
|
+
}
|
|
54
|
+
}
|