@pairbo/ui-kit 0.0.1 → 0.0.3
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/dist/pairbo.es.js +15027 -0
- package/dist/pairbo.umd.js +1633 -0
- package/dist/src/components/button/button.component.d.ts +32 -0
- package/dist/src/components/button/button.d.ts +8 -0
- package/dist/src/components/button/button.styles.d.ts +2 -0
- package/dist/src/components/button-group/button-group.component.d.ts +23 -0
- package/dist/src/components/button-group/button-group.d.ts +8 -0
- package/dist/src/components/button-group/button-group.styles.d.ts +2 -0
- package/dist/src/components/card-selection/card-selection.component.d.ts +23 -0
- package/dist/src/components/card-selection/card-selection.d.ts +8 -0
- package/dist/src/components/card-selection/card-selection.styles.d.ts +2 -0
- package/dist/src/components/category/category.component.d.ts +13 -0
- package/dist/src/components/category/category.d.ts +8 -0
- package/dist/src/components/category/category.styles.d.ts +2 -0
- package/dist/src/components/category-image/category-image.component.d.ts +23 -0
- package/dist/src/components/category-image/category-image.d.ts +8 -0
- package/dist/src/components/category-image/category-image.styles.d.ts +2 -0
- package/dist/src/components/drawer/drawer.component.d.ts +28 -0
- package/dist/src/components/drawer/drawer.d.ts +8 -0
- package/dist/src/components/drawer/drawer.styles.d.ts +2 -0
- package/dist/src/components/editor/editor.component.d.ts +24 -0
- package/dist/src/components/editor/editor.d.ts +8 -0
- package/dist/src/components/editor/editor.styles.d.ts +2 -0
- package/dist/src/components/fabric-example/fabric-example.component.d.ts +26 -0
- package/dist/src/components/fabric-example/fabric-example.d.ts +8 -0
- package/dist/src/components/fabric-example/fabric-example.styles.d.ts +2 -0
- package/dist/src/components/image-slider/editor-card-slider.component.d.ts +41 -0
- package/dist/src/components/image-slider/editor-card-slider.d.ts +8 -0
- package/dist/src/components/image-slider/editor-card-slider.styles.d.ts +2 -0
- package/dist/src/components/main.d.ts +15 -0
- package/dist/src/components/message-selector/message-selector.component.d.ts +38 -0
- package/dist/src/components/message-selector/message-selector.d.ts +8 -0
- package/dist/src/components/message-selector/message-selector.styles.d.ts +2 -0
- package/dist/src/components/message-selector/message-selector.test.d.ts +1 -0
- package/dist/src/components/page-manager/page-manager.component.d.ts +41 -0
- package/dist/src/components/page-manager/page-manager.d.ts +8 -0
- package/dist/src/components/page-manager/page-manager.styles.d.ts +2 -0
- package/dist/src/components/radio-button/radio-button.component.d.ts +37 -0
- package/dist/src/components/radio-button/radio-button.d.ts +8 -0
- package/dist/src/components/radio-button/radio-button.styles.d.ts +2 -0
- package/dist/src/components/radio-group/radio-group.component.d.ts +56 -0
- package/dist/src/components/radio-group/radio-group.d.ts +8 -0
- package/dist/src/components/radio-group/radio-group.styles.d.ts +2 -0
- package/dist/src/components/selector/selector.component.d.ts +18 -0
- package/dist/src/components/selector/selector.d.ts +8 -0
- package/dist/src/components/selector/selector.styles.d.ts +2 -0
- package/dist/src/components/textarea/textarea.component.d.ts +78 -0
- package/dist/src/components/textarea/textarea.d.ts +8 -0
- package/dist/src/components/textarea/textarea.styles.d.ts +2 -0
- package/dist/src/components/type-form/type-form.component.d.ts +48 -0
- package/dist/src/components/type-form/type-form.d.ts +8 -0
- package/dist/src/components/type-form/type-form.styles.d.ts +2 -0
- package/dist/src/events/events.d.ts +1 -0
- package/dist/src/events/pbo-category-card-select.d.ts +8 -0
- package/dist/src/internal/form.d.ts +43 -0
- package/{src/internal/pairbo-element.ts → dist/src/internal/pairbo-element.d.ts} +21 -46
- package/dist/src/internal/slots.d.ts +12 -0
- package/dist/src/internal/watch.d.ts +28 -0
- package/dist/src/styles/component.styles.d.ts +2 -0
- package/dist/src/styles/form-control.styles.d.ts +2 -0
- package/package.json +12 -8
- package/.husky/pre-commit +0 -1
- package/.prettierignore +0 -16
- package/.prettierrc.json +0 -17
- package/cspell.json +0 -9
- package/dev.html +0 -101
- package/docs/README.md +0 -1
- package/docs/_includes/component.njk +0 -16
- package/docs/_includes/default.njk +0 -39
- package/docs/_includes/sidebar.njk +0 -16
- package/docs/eleventy.config.mjs +0 -72
- package/docs/pages/components/message-selector.md +0 -17
- package/docs/pages/fabric-example.html +0 -46
- package/docs/pages/fabric-example.js +0 -28
- package/docs/pages/index.md +0 -76
- package/eslint.config.mjs +0 -32
- package/ignote_temp +0 -3
- package/index.html +0 -162
- package/lint-stage.confg.js +0 -6
- package/pages/card-selection.html +0 -65
- package/pages/drawer.html +0 -47
- package/pages/editor.html +0 -45
- package/pages/page-mgn.html +0 -51
- package/pages/test_build.html +0 -47
- package/scripts/plop/plopfile.js +0 -51
- package/scripts/plop/templates/components/component.hbs +0 -34
- package/scripts/plop/templates/components/define.hbs +0 -10
- package/scripts/plop/templates/components/styles.hbs +0 -7
- package/src/components/button/button.component.ts +0 -93
- package/src/components/button/button.styles.ts +0 -273
- package/src/components/button/button.ts +0 -10
- package/src/components/button-group/button-group.component.ts +0 -36
- package/src/components/button-group/button-group.styles.ts +0 -7
- package/src/components/button-group/button-group.ts +0 -10
- package/src/components/card-selection/card-selection.component.ts +0 -43
- package/src/components/card-selection/card-selection.styles.ts +0 -7
- package/src/components/card-selection/card-selection.ts +0 -10
- package/src/components/category/category.component.ts +0 -91
- package/src/components/category/category.styles.ts +0 -27
- package/src/components/category/category.ts +0 -10
- package/src/components/category-image/category-image.component.ts +0 -38
- package/src/components/category-image/category-image.styles.ts +0 -11
- package/src/components/category-image/category-image.ts +0 -10
- package/src/components/drawer/drawer.component.ts +0 -82
- package/src/components/drawer/drawer.styles.ts +0 -54
- package/src/components/drawer/drawer.ts +0 -10
- package/src/components/editor/editor.component.ts +0 -135
- package/src/components/editor/editor.styles.ts +0 -13
- package/src/components/editor/editor.ts +0 -10
- package/src/components/fabric-example/fabric-example.component.ts +0 -268
- package/src/components/fabric-example/fabric-example.styles.ts +0 -23
- package/src/components/fabric-example/fabric-example.ts +0 -12
- package/src/components/image-slider/editor-card-slider.component.ts +0 -136
- package/src/components/image-slider/editor-card-slider.styles.ts +0 -46
- package/src/components/image-slider/editor-card-slider.ts +0 -9
- package/src/components/main.ts +0 -17
- package/src/components/message-selector/message-selector.component.ts +0 -154
- package/src/components/message-selector/message-selector.styles.ts +0 -16
- package/src/components/message-selector/message-selector.test.ts +0 -64
- package/src/components/message-selector/message-selector.ts +0 -13
- package/src/components/page-manager/page-manager.component.ts +0 -228
- package/src/components/page-manager/page-manager.styles.ts +0 -9
- package/src/components/page-manager/page-manager.ts +0 -10
- package/src/components/radio-button/radio-button.component.ts +0 -118
- package/src/components/radio-button/radio-button.styles.ts +0 -13
- package/src/components/radio-button/radio-button.ts +0 -10
- package/src/components/radio-group/radio-group.component.ts +0 -203
- package/src/components/radio-group/radio-group.styles.ts +0 -19
- package/src/components/radio-group/radio-group.ts +0 -10
- package/src/components/selector/selector.component.ts +0 -115
- package/src/components/selector/selector.styles.ts +0 -9
- package/src/components/selector/selector.ts +0 -10
- package/src/components/textarea/textarea.component.ts +0 -234
- package/src/components/textarea/textarea.styles.ts +0 -178
- package/src/components/textarea/textarea.ts +0 -10
- package/src/components/type-form/type-form.component.ts +0 -121
- package/src/components/type-form/type-form.styles.ts +0 -7
- package/src/components/type-form/type-form.ts +0 -10
- package/src/declaration.d.ts +0 -44
- package/src/events/events.ts +0 -1
- package/src/events/pbo-category-card-select.ts +0 -7
- package/src/internal/form.ts +0 -376
- package/src/internal/slots.ts +0 -54
- package/src/internal/watch.ts +0 -79
- package/src/styles/component.styles.ts +0 -17
- package/src/styles/form-control.styles.ts +0 -59
- package/temp +0 -20
- package/tsconfig.json +0 -28
- package/vite.config.ts +0 -26
- /package/{public → dist}/Greeting Card from Pairbo.png +0 -0
- /package/{src/components/fabric-example/fabric-example.test.ts → dist/src/components/fabric-example/fabric-example.test.d.ts} +0 -0
- /package/{src → dist/src}/themes/default.css +0 -0
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { customElement, property, query, state } from "lit/decorators.js";
|
|
2
|
-
import { html, LitElement } from "lit";
|
|
3
|
-
import type { CSSResultGroup } from "lit";
|
|
4
|
-
import componentStyles from "../../styles/component.styles.js";
|
|
5
|
-
import PairboElement from "../../internal/pairbo-element.js";
|
|
6
|
-
import styles from "./type-form.styles.js";
|
|
7
|
-
import PboSelector from "../selector/selector.component.js";
|
|
8
|
-
import PboTextarea from "../textarea/textarea.component.js";
|
|
9
|
-
import PboRadioGroup from "../radio-group/radio-group.component.js";
|
|
10
|
-
import PboButton from "../button/button.component.js";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @summary Short summary of the component's intended use.
|
|
14
|
-
* @status experimental
|
|
15
|
-
*
|
|
16
|
-
* @dependency pbo-example
|
|
17
|
-
*
|
|
18
|
-
* @event pbo-event-name - Emitted as an example.
|
|
19
|
-
*
|
|
20
|
-
* @slot - The default slot.
|
|
21
|
-
* @slot example - An example slot.
|
|
22
|
-
*
|
|
23
|
-
* @csspart base - The component's base wrapper.
|
|
24
|
-
*
|
|
25
|
-
* @cssproperty --example - An example CSS custom property.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
@customElement("pbo-type-form")
|
|
29
|
-
export default class PboTypeForm extends PairboElement {
|
|
30
|
-
static styles: CSSResultGroup = [componentStyles, styles];
|
|
31
|
-
static dependencies = {
|
|
32
|
-
"pbo-selector": PboSelector,
|
|
33
|
-
"pbo-textarea": PboTextarea,
|
|
34
|
-
"pbo-color-radio-group": PboRadioGroup,
|
|
35
|
-
"pbo-radio-group": PboRadioGroup,
|
|
36
|
-
"pbo-radio-button": PboRadioGroup,
|
|
37
|
-
"pbo-button": PboButton,
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
@query(".greeting-text") greetingText!: PboTextarea;
|
|
41
|
-
@query(".font-selector") fontSelector!: PboSelector;
|
|
42
|
-
@query(".text-color") textColor!: PboRadioGroup;
|
|
43
|
-
@query(".text-alignment") textAlignment!: PboRadioGroup;
|
|
44
|
-
|
|
45
|
-
@state()
|
|
46
|
-
private formData = {
|
|
47
|
-
font: "",
|
|
48
|
-
text: "",
|
|
49
|
-
color: "",
|
|
50
|
-
alignment: "",
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
@property({ type: String, reflect: true }) cardInnerImageUrl = "../../../public/Greeting Card from Pairbo.png";
|
|
54
|
-
|
|
55
|
-
get form() {
|
|
56
|
-
return {
|
|
57
|
-
font: this.fontSelector?.value,
|
|
58
|
-
text: this.greetingText?.value,
|
|
59
|
-
color: this.textColor?.value,
|
|
60
|
-
alignment: this.textAlignment?.value,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
private handleFormChange(e: Event) {
|
|
65
|
-
const target = e.target as HTMLElement;
|
|
66
|
-
|
|
67
|
-
// Update the form data based on which element changed
|
|
68
|
-
if (target.classList.contains("font-selector")) {
|
|
69
|
-
this.formData.font = (target as PboSelector)?.value?.value || " Font form control not implemented yet";
|
|
70
|
-
} else if (target.classList.contains("greeting-text")) {
|
|
71
|
-
this.formData.text = (target as PboTextarea).value;
|
|
72
|
-
} else if (target.classList.contains("text-color")) {
|
|
73
|
-
this.formData.color = (target as PboRadioGroup).value;
|
|
74
|
-
} else if (target.classList.contains("text-alignment")) {
|
|
75
|
-
this.formData.alignment = (target as PboRadioGroup).value;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Emit the change event with the current form data
|
|
79
|
-
this.emit("pbo-change", {
|
|
80
|
-
detail: this.form,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
hostConnected() {
|
|
85
|
-
this.addEventListener("pbo-change", this.handleFormChange);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
hostDisconnected() {
|
|
89
|
-
this.removeEventListener("pbo-change", this.handleFormChange);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
render() {
|
|
93
|
-
return html`
|
|
94
|
-
<form class="typing-form">
|
|
95
|
-
<pbo-selector
|
|
96
|
-
class="font-selector"
|
|
97
|
-
.fonts="${[
|
|
98
|
-
{ value: "Monsieur La Doulaise", label: "Monsieur La Doulaise", font: "Monsieur La Doulaise, serif" },
|
|
99
|
-
{ value: "Open Sans", label: "Open Sans", font: "'Open Sans', sans-serif" },
|
|
100
|
-
{ value: "Kablammo", label: "Kablammo", font: "Kablammo" },
|
|
101
|
-
]}"
|
|
102
|
-
@pbo-change=${this.handleFormChange}
|
|
103
|
-
></pbo-selector>
|
|
104
|
-
<pbo-textarea class="greeting-text" @pbo-input=${this.handleFormChange}></pbo-textarea>
|
|
105
|
-
|
|
106
|
-
<pbo-radio-group class="text-color" @pbo-change=${this.handleFormChange}>
|
|
107
|
-
<pbo-radio-button value="rgb(255,255,255)" size="small" circle></pbo-radio-button>
|
|
108
|
-
<pbo-radio-button value="rgb(0,0,0)" size="small" circle></pbo-radio-button>
|
|
109
|
-
</pbo-radio-group>
|
|
110
|
-
|
|
111
|
-
<pbo-radio-group class="text-alignment" @pbo-change=${this.handleFormChange}>
|
|
112
|
-
<pbo-radio-button value="left">Left</pbo-radio-button>
|
|
113
|
-
<pbo-radio-button value="center">Center</pbo-radio-button>
|
|
114
|
-
<pbo-radio-button value="right">Right</pbo-radio-button>
|
|
115
|
-
</pbo-radio-group>
|
|
116
|
-
|
|
117
|
-
<pbo-button>Save and Continue</pbo-button>
|
|
118
|
-
</form>
|
|
119
|
-
`;
|
|
120
|
-
}
|
|
121
|
-
}
|
package/src/declaration.d.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
declare module "*.css" {
|
|
2
|
-
const styles: string;
|
|
3
|
-
export default styles;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
// Declare that CSS files can be imported as a string
|
|
7
|
-
declare module "*.css?inline" {
|
|
8
|
-
const content: string;
|
|
9
|
-
export default content;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
declare interface Card {
|
|
13
|
-
id: string;
|
|
14
|
-
name: string;
|
|
15
|
-
category: string | string[];
|
|
16
|
-
medias: {
|
|
17
|
-
cover: {
|
|
18
|
-
url: string;
|
|
19
|
-
alt: string;
|
|
20
|
-
};
|
|
21
|
-
back: {
|
|
22
|
-
url: string;
|
|
23
|
-
alt: string;
|
|
24
|
-
};
|
|
25
|
-
inner: {
|
|
26
|
-
url: string;
|
|
27
|
-
alt: string;
|
|
28
|
-
};
|
|
29
|
-
render_1: {
|
|
30
|
-
url: string;
|
|
31
|
-
alt: string;
|
|
32
|
-
};
|
|
33
|
-
render_2: {
|
|
34
|
-
url: string;
|
|
35
|
-
alt: string;
|
|
36
|
-
};
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
declare interface Category {
|
|
41
|
-
id: string;
|
|
42
|
-
name: string;
|
|
43
|
-
cards: Card[];
|
|
44
|
-
}
|
package/src/events/events.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type { PboCategoryCardSelectEvent } from "./pbo-category-card-select.js";
|
package/src/internal/form.ts
DELETED
|
@@ -1,376 +0,0 @@
|
|
|
1
|
-
import { ReactiveController, ReactiveControllerHost } from "lit";
|
|
2
|
-
import { PairboFormControl } from "./pairbo-element";
|
|
3
|
-
import { PboButton } from "../components/main";
|
|
4
|
-
|
|
5
|
-
export const formCollections: WeakMap<HTMLFormElement, Set<PairboFormControl>> = new WeakMap();
|
|
6
|
-
|
|
7
|
-
// We store a WeakMap of reportValidity() overloads so we can override it when form controls connect to the DOM and
|
|
8
|
-
// restore the original behavior when they disconnect.
|
|
9
|
-
//
|
|
10
|
-
const reportValidityOverloads: WeakMap<HTMLFormElement, () => boolean> = new WeakMap();
|
|
11
|
-
const checkValidityOverloads: WeakMap<HTMLFormElement, () => boolean> = new WeakMap();
|
|
12
|
-
|
|
13
|
-
//
|
|
14
|
-
// We store a Set of controls that users have interacted with. This allows us to determine the interaction state
|
|
15
|
-
// without littering the DOM with additional data attributes.
|
|
16
|
-
//
|
|
17
|
-
const userInteractedControls: WeakSet<PairboFormControl> = new WeakSet();
|
|
18
|
-
|
|
19
|
-
//
|
|
20
|
-
// We store a WeakMap of interactions for each form control so we can track when all conditions are met for validation.
|
|
21
|
-
//
|
|
22
|
-
const interactions = new WeakMap<PairboFormControl, string[]>();
|
|
23
|
-
|
|
24
|
-
export interface FormControlControllerOptions {
|
|
25
|
-
// The form element that the control is associated with.
|
|
26
|
-
form: (input: PairboFormControl) => HTMLFormElement | null;
|
|
27
|
-
// The name of the control.
|
|
28
|
-
name: (input: PairboFormControl) => string;
|
|
29
|
-
// The default value of the control.
|
|
30
|
-
defaultValue: (input: PairboFormControl) => unknown;
|
|
31
|
-
// The value of the control.
|
|
32
|
-
value: (input: PairboFormControl) => unknown | unknown[];
|
|
33
|
-
// Whether the control is disabled.
|
|
34
|
-
disabled: (input: PairboFormControl) => boolean;
|
|
35
|
-
// When the control is invalid, the error message that should be shown to the user.
|
|
36
|
-
reportValidity: (input: PairboFormControl) => boolean;
|
|
37
|
-
//check if the control is valid
|
|
38
|
-
checkValidity: (input: PairboFormControl) => boolean;
|
|
39
|
-
// set value of the control
|
|
40
|
-
setValue: (input: PairboFormControl, value: unknown) => void;
|
|
41
|
-
// An array of event names to listen to.
|
|
42
|
-
assumeInteractionOn: string[];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export class FormControlController implements ReactiveController {
|
|
46
|
-
host: PairboFormControl & ReactiveControllerHost;
|
|
47
|
-
form?: HTMLFormElement | null;
|
|
48
|
-
options: FormControlControllerOptions;
|
|
49
|
-
|
|
50
|
-
constructor(host: PairboFormControl & ReactiveControllerHost, options?: Partial<FormControlControllerOptions>) {
|
|
51
|
-
console.log({ host });
|
|
52
|
-
(this.host = host).addController(this);
|
|
53
|
-
this.options = {
|
|
54
|
-
form: input => {
|
|
55
|
-
const formId = input.form;
|
|
56
|
-
|
|
57
|
-
if (formId) {
|
|
58
|
-
const root = input.getRootNode() as Document | ShadowRoot | HTMLElement;
|
|
59
|
-
const form = root.querySelector(`#${formId}`);
|
|
60
|
-
|
|
61
|
-
if (form) {
|
|
62
|
-
return form as HTMLFormElement;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return input.closest("form");
|
|
66
|
-
},
|
|
67
|
-
name: input => input.name,
|
|
68
|
-
value: input => input.value,
|
|
69
|
-
defaultValue: input => input.defaultValue,
|
|
70
|
-
disabled: input => input.disabled || false,
|
|
71
|
-
reportValidity: input => (typeof input.reportValidity === "function" ? input.reportValidity() : true),
|
|
72
|
-
checkValidity: input => (typeof input.checkValidity === "function" ? input.checkValidity() : true),
|
|
73
|
-
setValue: (input, value: string) => (input.value = value),
|
|
74
|
-
assumeInteractionOn: ["pbo-input"],
|
|
75
|
-
...options,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
hostConnected() {
|
|
80
|
-
const form = this.options.form(this.host);
|
|
81
|
-
|
|
82
|
-
if (form) {
|
|
83
|
-
this.attachForm(form);
|
|
84
|
-
}
|
|
85
|
-
// Listen for interactions
|
|
86
|
-
interactions.set(this.host, []);
|
|
87
|
-
console.log({ interactions });
|
|
88
|
-
|
|
89
|
-
this.options.assumeInteractionOn.forEach(event => {
|
|
90
|
-
this.host.addEventListener(event, this.handleInteraction);
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
hostDisconnected() {
|
|
94
|
-
this.detachForm();
|
|
95
|
-
|
|
96
|
-
// Clean up interactions
|
|
97
|
-
interactions.delete(this.host);
|
|
98
|
-
this.options.assumeInteractionOn.forEach(event => {
|
|
99
|
-
this.host.removeEventListener(event, this.handleInteraction);
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
hostUpdated() {
|
|
104
|
-
const form = this.options.form(this.host);
|
|
105
|
-
|
|
106
|
-
// Detach if the form no longer exists
|
|
107
|
-
if (!form) {
|
|
108
|
-
this.detachForm();
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// If the form has changed, reattach it
|
|
112
|
-
if (form && this.form !== form) {
|
|
113
|
-
this.detachForm();
|
|
114
|
-
this.attachForm(form);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (this.host.hasUpdated) {
|
|
118
|
-
this.setValidity(this.host.validity.valid);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
private attachForm(form?: HTMLFormElement) {
|
|
123
|
-
if (form) {
|
|
124
|
-
this.form = form;
|
|
125
|
-
|
|
126
|
-
// Add this element to the form's collection
|
|
127
|
-
if (formCollections.has(this.form)) {
|
|
128
|
-
formCollections.get(this.form)!.add(this.host);
|
|
129
|
-
} else {
|
|
130
|
-
formCollections.set(this.form, new Set<PairboFormControl>([this.host]));
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
this.form.addEventListener("formdata", this.handleFormData);
|
|
134
|
-
this.form.addEventListener("submit", this.handleFormSubmit);
|
|
135
|
-
this.form.addEventListener("reset", this.handleFormReset);
|
|
136
|
-
|
|
137
|
-
// Overload the form's reportValidity() method so it looks at Shoelace form controls
|
|
138
|
-
if (!reportValidityOverloads.has(this.form)) {
|
|
139
|
-
reportValidityOverloads.set(this.form, this.form.reportValidity);
|
|
140
|
-
this.form.reportValidity = () => this.reportFormValidity();
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Overload the form's checkValidity() method so it looks at Shoelace form controls
|
|
144
|
-
if (!checkValidityOverloads.has(this.form)) {
|
|
145
|
-
checkValidityOverloads.set(this.form, this.form.checkValidity);
|
|
146
|
-
this.form.checkValidity = () => this.checkFormValidity();
|
|
147
|
-
}
|
|
148
|
-
} else {
|
|
149
|
-
this.form = undefined;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
private detachForm() {
|
|
153
|
-
if (!this.form) return;
|
|
154
|
-
|
|
155
|
-
const formCollection = formCollections.get(this.form);
|
|
156
|
-
|
|
157
|
-
if (!formCollection) {
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// Remove this host from the form's collection
|
|
162
|
-
formCollection.delete(this.host);
|
|
163
|
-
|
|
164
|
-
// Check to make sure there's no other form controls in the collection. If we do this
|
|
165
|
-
// without checking if any other controls are still in the collection, then we will wipe out the
|
|
166
|
-
// validity checks for all other elements.
|
|
167
|
-
// see: https://github.com/shoelace-style/shoelace/issues/1703
|
|
168
|
-
if (formCollection.size <= 0) {
|
|
169
|
-
this.form.removeEventListener("formdata", this.handleFormData);
|
|
170
|
-
this.form.removeEventListener("submit", this.handleFormSubmit);
|
|
171
|
-
this.form.removeEventListener("reset", this.handleFormReset);
|
|
172
|
-
|
|
173
|
-
// Remove the overload and restore the original method
|
|
174
|
-
if (reportValidityOverloads.has(this.form)) {
|
|
175
|
-
this.form.reportValidity = reportValidityOverloads.get(this.form)!;
|
|
176
|
-
reportValidityOverloads.delete(this.form);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (checkValidityOverloads.has(this.form)) {
|
|
180
|
-
this.form.checkValidity = checkValidityOverloads.get(this.form)!;
|
|
181
|
-
checkValidityOverloads.delete(this.form);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// So it looks weird here to not always set the form to undefined. But I _think_ if we unattach this.form here,
|
|
185
|
-
// we end up in this fun spot where future validity checks don't have a reference to the form validity handler.
|
|
186
|
-
// First form element in sets the validity handler. So we can't clean up `this.form` until there are no other form elements in the form.
|
|
187
|
-
this.form = undefined;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Append the control's name and value to the given FormData object.
|
|
192
|
-
private handleFormData = (event: FormDataEvent) => {
|
|
193
|
-
const disabled = this.options.disabled(this.host);
|
|
194
|
-
const name = this.options.name(this.host);
|
|
195
|
-
const value = this.options.value(this.host);
|
|
196
|
-
if (
|
|
197
|
-
this.host.isConnected &&
|
|
198
|
-
!disabled &&
|
|
199
|
-
typeof name === "string" &&
|
|
200
|
-
name.length > 0 &&
|
|
201
|
-
typeof value !== "undefined"
|
|
202
|
-
) {
|
|
203
|
-
if (Array.isArray(value)) {
|
|
204
|
-
(value as unknown[]).forEach(val => {
|
|
205
|
-
event.formData.append(name, (val as string | number | boolean).toString());
|
|
206
|
-
});
|
|
207
|
-
} else {
|
|
208
|
-
event.formData.append(name, (value as string | number | boolean).toString());
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
private handleFormSubmit = (event: Event) => {
|
|
214
|
-
const disabled = this.options.disabled(this.host);
|
|
215
|
-
const reportValidity = this.options.reportValidity;
|
|
216
|
-
if (this.form && !this.form.noValidate) {
|
|
217
|
-
formCollections.get(this.form)?.forEach(control => {
|
|
218
|
-
this.setUserInteracted(control, true);
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (this.form && !this.form.noValidate && !disabled && !reportValidity(this.host)) {
|
|
223
|
-
event?.preventDefault();
|
|
224
|
-
event?.stopImmediatePropagation();
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
private handleFormReset = () => {
|
|
229
|
-
this.options.setValue(this.host, this.options.defaultValue(this.host));
|
|
230
|
-
this.setUserInteracted(this.host, false);
|
|
231
|
-
interactions.set(this.host, []);
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
private handleInteraction = (event: Event) => {
|
|
235
|
-
const emittedEvents = interactions.get(this.host)!;
|
|
236
|
-
if (!emittedEvents.includes(event.type)) {
|
|
237
|
-
emittedEvents.push(event.type);
|
|
238
|
-
}
|
|
239
|
-
if (emittedEvents.length === this.options.assumeInteractionOn.length) {
|
|
240
|
-
this.setUserInteracted(this.host, true);
|
|
241
|
-
}
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
private checkFormValidity = () => {
|
|
245
|
-
if (this.form && !this.form.noValidate) {
|
|
246
|
-
const elements = this.form.querySelectorAll<HTMLInputElement>("*");
|
|
247
|
-
for (const element of elements) {
|
|
248
|
-
if (typeof element.checkValidity === "function") {
|
|
249
|
-
if (!element.checkValidity()) {
|
|
250
|
-
return false;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
return true;
|
|
256
|
-
};
|
|
257
|
-
private reportFormValidity() {
|
|
258
|
-
if (this.form && !this.form.noValidate) {
|
|
259
|
-
const elements = this.form.querySelectorAll<HTMLInputElement>("*");
|
|
260
|
-
for (const element of elements) {
|
|
261
|
-
if (typeof element.reportValidity === "function") {
|
|
262
|
-
if (!element.reportValidity()) {
|
|
263
|
-
return false;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
return true;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
private setUserInteracted(el: PairboFormControl, hasInteracted: boolean) {
|
|
272
|
-
if (hasInteracted) {
|
|
273
|
-
userInteractedControls.add(el);
|
|
274
|
-
} else {
|
|
275
|
-
userInteractedControls.delete(el);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
el.requestUpdate();
|
|
279
|
-
}
|
|
280
|
-
private doAction = (type: "submit" | "reset", submitter?: HTMLInputElement | PboButton) => {
|
|
281
|
-
if (this.form) {
|
|
282
|
-
const button = document.createElement("button");
|
|
283
|
-
button.type = type;
|
|
284
|
-
button.style.position = "absolute";
|
|
285
|
-
button.style.width = "0";
|
|
286
|
-
button.style.height = "0";
|
|
287
|
-
button.style.clipPath = "inset(50%)";
|
|
288
|
-
button.style.overflow = "hidden";
|
|
289
|
-
button.style.whiteSpace = "nowrap";
|
|
290
|
-
if (submitter) {
|
|
291
|
-
button.name = submitter.name;
|
|
292
|
-
button.value = submitter.value;
|
|
293
|
-
|
|
294
|
-
["formation", "formenctype", "formmethod", "formnovalidate", "formtarget"].forEach(attr => {
|
|
295
|
-
if (submitter.hasAttribute(attr)) {
|
|
296
|
-
button.setAttribute(attr, submitter.getAttribute(attr)!);
|
|
297
|
-
}
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
this.form.append(button);
|
|
302
|
-
button.click();
|
|
303
|
-
button.remove();
|
|
304
|
-
}
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
getForm() {
|
|
308
|
-
return this.form ?? null;
|
|
309
|
-
}
|
|
310
|
-
reset(submitter?: HTMLInputElement | PboButton) {
|
|
311
|
-
this.doAction("reset", submitter);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
submit(submitter?: HTMLInputElement | PboButton) {
|
|
315
|
-
this.doAction("submit", submitter);
|
|
316
|
-
}
|
|
317
|
-
setValidity(isValid: boolean) {
|
|
318
|
-
const host = this.host;
|
|
319
|
-
const hasInteracted = Boolean(userInteractedControls.has(host));
|
|
320
|
-
const required = Boolean(host.required);
|
|
321
|
-
|
|
322
|
-
host.toggleAttribute("data-required", required);
|
|
323
|
-
host.toggleAttribute("data-optional", !required);
|
|
324
|
-
host.toggleAttribute("data-invalid", !isValid);
|
|
325
|
-
host.toggleAttribute("data-valid", isValid);
|
|
326
|
-
host.toggleAttribute("data-user-invalid", hasInteracted && !isValid);
|
|
327
|
-
host.toggleAttribute("data-user-valid", hasInteracted && isValid);
|
|
328
|
-
}
|
|
329
|
-
updateValidity() {
|
|
330
|
-
const host = this.host;
|
|
331
|
-
this.setValidity(host.validity.valid);
|
|
332
|
-
}
|
|
333
|
-
emitInvalidEvent(originalInvalidEvent?: Event) {
|
|
334
|
-
const pboInvalidEvent = new CustomEvent<Record<PropertyKey, never>>("pbo-invalid", {
|
|
335
|
-
bubbles: false,
|
|
336
|
-
composed: false,
|
|
337
|
-
cancelable: true,
|
|
338
|
-
detail: {},
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
if (!originalInvalidEvent) {
|
|
342
|
-
pboInvalidEvent.preventDefault();
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
if (!this.host.dispatchEvent(pboInvalidEvent)) {
|
|
346
|
-
originalInvalidEvent?.preventDefault();
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
export const validValidityState: ValidityState = Object.freeze({
|
|
352
|
-
badInput: false,
|
|
353
|
-
customError: false,
|
|
354
|
-
patternMismatch: false,
|
|
355
|
-
rangeOverflow: false,
|
|
356
|
-
rangeUnderflow: false,
|
|
357
|
-
stepMismatch: false,
|
|
358
|
-
tooLong: false,
|
|
359
|
-
tooShort: false,
|
|
360
|
-
typeMismatch: false,
|
|
361
|
-
valid: true,
|
|
362
|
-
valueMissing: false,
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
// A validity state object that represents `value missing`
|
|
366
|
-
export const valueMissingValidityState: ValidityState = Object.freeze({
|
|
367
|
-
...validValidityState,
|
|
368
|
-
valid: false,
|
|
369
|
-
valueMissing: false,
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
export const customErrorValidityState: ValidityState = Object.freeze({
|
|
373
|
-
...validValidityState,
|
|
374
|
-
valid: false,
|
|
375
|
-
customError: true,
|
|
376
|
-
});
|
package/src/internal/slots.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import type { ReactiveController, ReactiveControllerHost } from "lit";
|
|
2
|
-
|
|
3
|
-
export class HasSlotController implements ReactiveController {
|
|
4
|
-
host: ReactiveControllerHost & Element;
|
|
5
|
-
slotNames: string[] = [];
|
|
6
|
-
constructor(host: ReactiveControllerHost & Element, ...slotNames: string[]) {
|
|
7
|
-
(this.host = host).addController(this);
|
|
8
|
-
this.slotNames = slotNames;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
private hasDefaultSlot() {
|
|
12
|
-
return [...this.host.childNodes].some(node => {
|
|
13
|
-
// The node is a text node and it's not empty
|
|
14
|
-
if (node.nodeType === node.TEXT_NODE && node.textContent?.trim() !== "") {
|
|
15
|
-
return true;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// The node is an element node
|
|
19
|
-
if (node.nodeType === node.ELEMENT_NODE) {
|
|
20
|
-
const element = node as Element;
|
|
21
|
-
const tagName = element.tagName.toLowerCase();
|
|
22
|
-
// If the tag is visually hidden, ignore it
|
|
23
|
-
if (tagName === "pbo-visually-hidden") {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
// So if the element has no slot attribute, it's in the default slot
|
|
27
|
-
if (!element.hasAttribute("slot")) {
|
|
28
|
-
return true;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return false;
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
private hasNamedSlot(name: string) {
|
|
36
|
-
return this.host.querySelector(`:scope > [slot="${name}]`) !== null;
|
|
37
|
-
}
|
|
38
|
-
test(slotName: string) {
|
|
39
|
-
return slotName === "[default]" ? this.hasDefaultSlot() : this.hasNamedSlot(slotName);
|
|
40
|
-
}
|
|
41
|
-
hostConnected() {
|
|
42
|
-
this.host.shadowRoot!.addEventListener("slotchange", this.handleSlotChange);
|
|
43
|
-
}
|
|
44
|
-
hostDisconnected() {
|
|
45
|
-
this.host.shadowRoot!.removeEventListener("slotchange", this.handleSlotChange);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
private handleSlotChange = (event: Event) => {
|
|
49
|
-
const slot = event.target as HTMLSlotElement;
|
|
50
|
-
if ((this.slotNames.includes("[default]") && !slot.name) || (slot.name && this.slotNames.includes(slot.name))) {
|
|
51
|
-
this.host.requestUpdate();
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
}
|