@pairbo/ui-kit 0.0.1

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.
Files changed (94) hide show
  1. package/.husky/pre-commit +1 -0
  2. package/.prettierignore +16 -0
  3. package/.prettierrc.json +17 -0
  4. package/README.md +61 -0
  5. package/cspell.json +9 -0
  6. package/dev.html +101 -0
  7. package/docs/README.md +1 -0
  8. package/docs/_includes/component.njk +16 -0
  9. package/docs/_includes/default.njk +39 -0
  10. package/docs/_includes/sidebar.njk +16 -0
  11. package/docs/eleventy.config.mjs +72 -0
  12. package/docs/pages/components/message-selector.md +17 -0
  13. package/docs/pages/fabric-example.html +46 -0
  14. package/docs/pages/fabric-example.js +28 -0
  15. package/docs/pages/index.md +76 -0
  16. package/eslint.config.mjs +32 -0
  17. package/ignote_temp +3 -0
  18. package/index.html +162 -0
  19. package/lint-stage.confg.js +6 -0
  20. package/package.json +66 -0
  21. package/pages/card-selection.html +65 -0
  22. package/pages/drawer.html +47 -0
  23. package/pages/editor.html +45 -0
  24. package/pages/page-mgn.html +51 -0
  25. package/pages/test_build.html +47 -0
  26. package/public/Greeting Card from Pairbo.png +0 -0
  27. package/scripts/plop/plopfile.js +51 -0
  28. package/scripts/plop/templates/components/component.hbs +34 -0
  29. package/scripts/plop/templates/components/define.hbs +10 -0
  30. package/scripts/plop/templates/components/styles.hbs +7 -0
  31. package/src/components/button/button.component.ts +93 -0
  32. package/src/components/button/button.styles.ts +273 -0
  33. package/src/components/button/button.ts +10 -0
  34. package/src/components/button-group/button-group.component.ts +36 -0
  35. package/src/components/button-group/button-group.styles.ts +7 -0
  36. package/src/components/button-group/button-group.ts +10 -0
  37. package/src/components/card-selection/card-selection.component.ts +43 -0
  38. package/src/components/card-selection/card-selection.styles.ts +7 -0
  39. package/src/components/card-selection/card-selection.ts +10 -0
  40. package/src/components/category/category.component.ts +91 -0
  41. package/src/components/category/category.styles.ts +27 -0
  42. package/src/components/category/category.ts +10 -0
  43. package/src/components/category-image/category-image.component.ts +38 -0
  44. package/src/components/category-image/category-image.styles.ts +11 -0
  45. package/src/components/category-image/category-image.ts +10 -0
  46. package/src/components/drawer/drawer.component.ts +82 -0
  47. package/src/components/drawer/drawer.styles.ts +54 -0
  48. package/src/components/drawer/drawer.ts +10 -0
  49. package/src/components/editor/editor.component.ts +135 -0
  50. package/src/components/editor/editor.styles.ts +13 -0
  51. package/src/components/editor/editor.ts +10 -0
  52. package/src/components/fabric-example/fabric-example.component.ts +268 -0
  53. package/src/components/fabric-example/fabric-example.styles.ts +23 -0
  54. package/src/components/fabric-example/fabric-example.test.ts +0 -0
  55. package/src/components/fabric-example/fabric-example.ts +12 -0
  56. package/src/components/image-slider/editor-card-slider.component.ts +136 -0
  57. package/src/components/image-slider/editor-card-slider.styles.ts +46 -0
  58. package/src/components/image-slider/editor-card-slider.ts +9 -0
  59. package/src/components/main.ts +17 -0
  60. package/src/components/message-selector/message-selector.component.ts +154 -0
  61. package/src/components/message-selector/message-selector.styles.ts +16 -0
  62. package/src/components/message-selector/message-selector.test.ts +64 -0
  63. package/src/components/message-selector/message-selector.ts +13 -0
  64. package/src/components/page-manager/page-manager.component.ts +228 -0
  65. package/src/components/page-manager/page-manager.styles.ts +9 -0
  66. package/src/components/page-manager/page-manager.ts +10 -0
  67. package/src/components/radio-button/radio-button.component.ts +118 -0
  68. package/src/components/radio-button/radio-button.styles.ts +13 -0
  69. package/src/components/radio-button/radio-button.ts +10 -0
  70. package/src/components/radio-group/radio-group.component.ts +203 -0
  71. package/src/components/radio-group/radio-group.styles.ts +19 -0
  72. package/src/components/radio-group/radio-group.ts +10 -0
  73. package/src/components/selector/selector.component.ts +115 -0
  74. package/src/components/selector/selector.styles.ts +9 -0
  75. package/src/components/selector/selector.ts +10 -0
  76. package/src/components/textarea/textarea.component.ts +234 -0
  77. package/src/components/textarea/textarea.styles.ts +178 -0
  78. package/src/components/textarea/textarea.ts +10 -0
  79. package/src/components/type-form/type-form.component.ts +121 -0
  80. package/src/components/type-form/type-form.styles.ts +7 -0
  81. package/src/components/type-form/type-form.ts +10 -0
  82. package/src/declaration.d.ts +44 -0
  83. package/src/events/events.ts +1 -0
  84. package/src/events/pbo-category-card-select.ts +7 -0
  85. package/src/internal/form.ts +376 -0
  86. package/src/internal/pairbo-element.ts +85 -0
  87. package/src/internal/slots.ts +54 -0
  88. package/src/internal/watch.ts +79 -0
  89. package/src/styles/component.styles.ts +17 -0
  90. package/src/styles/form-control.styles.ts +59 -0
  91. package/src/themes/default.css +414 -0
  92. package/temp +20 -0
  93. package/tsconfig.json +28 -0
  94. package/vite.config.ts +26 -0
@@ -0,0 +1,136 @@
1
+ import { customElement, property, query, queryAll, state } from "lit/decorators.js";
2
+ import { css, html, LitElement, unsafeCSS } from "lit";
3
+ import type { CSSResultGroup, PropertyValues } from "lit";
4
+ import componentStyles from "../../styles/component.styles.js";
5
+ import PairboElement from "../../internal/pairbo-element.js";
6
+ import styles from "./editor-card-slider.styles.js";
7
+ // Default theme
8
+ import splideCss from "@splidejs/splide/dist/css/themes/splide-default.min.css?inline";
9
+ import Splide from "@splidejs/splide";
10
+ import FabricExample from "../fabric-example/fabric-example.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-editor-card-slider")
29
+ export default class PboEditorCardSlider extends PairboElement {
30
+ // static styles: CSSResultGroup = [componentStyles, styles];
31
+ static styles: CSSResultGroup = [componentStyles, styles, unsafeCSS(splideCss)];
32
+ static dependencies = {
33
+ "fabric-example": FabricExample,
34
+ };
35
+
36
+ @property({ type: Object }) card: Card | null = null;
37
+ @property({ type: Number, reflect: true }) focusIndex = 0;
38
+
39
+ @property({ type: Object }) livePreviewProps: {
40
+ font: string;
41
+ text: string;
42
+ color: string;
43
+ alignment: string;
44
+ } = { font: "Monsieur La Doulaise", text: "", color: "rgb(0,0,0)", alignment: "left" };
45
+
46
+ @query("#thumbnails") thumbnailCarousel!: HTMLDivElement;
47
+ @query("#main-carousel") mainCarousel!: HTMLDivElement;
48
+ @queryAll(".thumbnail") thumbnailElements!: NodeListOf<HTMLDivElement>;
49
+ @state() thumbnailSplide!: Splide;
50
+ @state() mainSplide!: Splide;
51
+
52
+ protected firstUpdated(): void {
53
+ this.mainSplide = new Splide(this.mainCarousel, {
54
+ width: 300,
55
+ height: 400,
56
+ pagination: false,
57
+ arrows: false,
58
+ direction: "ttb",
59
+ cover: true,
60
+ });
61
+
62
+ const initThumbnail = (thumbnail: HTMLDivElement, index: number) => {
63
+ thumbnail.addEventListener("click", () => {
64
+ this.mainSplide.go(index);
65
+ });
66
+ };
67
+
68
+ console.log(this.thumbnailElements);
69
+ for (let i = 0; i < this.thumbnailElements.length; i++) {
70
+ initThumbnail(this.thumbnailElements[i], i);
71
+ }
72
+ let current: Element | null = null;
73
+ this.mainSplide.on("mounted move", () => {
74
+ this.focusIndex = this.mainSplide.index;
75
+ if (current !== null) {
76
+ current.classList.remove("is-active");
77
+ }
78
+
79
+ let thumbnail = this.thumbnailElements[this.mainSplide.index];
80
+ if (thumbnail) {
81
+ thumbnail.classList.add("is-active");
82
+ current = thumbnail;
83
+ }
84
+ });
85
+
86
+ this.mainSplide.mount();
87
+ // The function to initialize each thumbnail.
88
+ }
89
+ updated(changedProperties: Map<string | number | symbol, unknown>) {
90
+ if (changedProperties.has("focusIndex")) {
91
+ this.mainSplide.go(this.focusIndex);
92
+ }
93
+ }
94
+
95
+ render() {
96
+ return html`
97
+ ${JSON.stringify(this.card)}
98
+ <div class="card--slider--wrapper">
99
+ <ul id="thumbnails" class="thumbnails">
100
+ <li class="thumbnail">
101
+ <img src="${this.card?.medias.cover.url || "https://picsum.photos/id/1/300/400"}" alt="" />
102
+ </li>
103
+ <li class="thumbnail">
104
+ <img src="${this.card?.medias.render_1.url || "https://picsum.photos/id/10/300/400"}" alt="" />
105
+ </li>
106
+ <li class="thumbnail">
107
+ <img src="${this.card?.medias.render_2.url || "https://picsum.photos/id/10/300/400"}" alt="" />
108
+ </li>
109
+ </ul>
110
+
111
+ <section id="main-carousel" class="splide" aria-label="My Awesome Gallery">
112
+ <div class="splide__track">
113
+ <ul class="splide__list">
114
+ <li class="splide__slide">
115
+ ${this.card?.medias.cover.url}
116
+ <img src="${this.card?.medias.cover.url || "https://picsum.photos/id/1/300/400"}" alt="" />
117
+ </li>
118
+ <li class="splide__slide">
119
+ <fabric-example
120
+ backgroundUrl="${this.card?.medias.render_1.url || "https://picsum.photos/id/10/300/400"}"
121
+ alignment=${this.livePreviewProps?.alignment || "left"}
122
+ message=${this.livePreviewProps?.text}
123
+ color=${this.livePreviewProps?.color}
124
+ fontFamily=${this.livePreviewProps?.font}
125
+ ></fabric-example>
126
+ </li>
127
+ <li class="splide__slide">
128
+ <img src="${this.card?.medias.render_2.url || "https://picsum.photos/id/10/300/400"}" alt="" />
129
+ </li>
130
+ </ul>
131
+ </div>
132
+ </section>
133
+ </div>
134
+ `;
135
+ }
136
+ }
@@ -0,0 +1,46 @@
1
+ import { css } from "lit";
2
+
3
+ export default css`
4
+ :host {
5
+ display: block;
6
+ }
7
+
8
+ .card--slider--wrapper {
9
+ display: flex;
10
+ }
11
+
12
+ .splide {
13
+ margin: 0 auto;
14
+ width: 100%;
15
+ }
16
+ img {
17
+ -webkit-user-drag: none;
18
+ pointer-events: none;
19
+ }
20
+ .thumbnails {
21
+ display: flex;
22
+ flex-direction: column;
23
+ gap: 0.5rem;
24
+ padding: 0;
25
+ justify-content: start;
26
+ }
27
+
28
+ .thumbnail {
29
+ width: 70px;
30
+ height: 70px;
31
+ overflow: hidden;
32
+ list-style: none;
33
+ margin: 0 0.2rem;
34
+ cursor: pointer;
35
+ opacity: 0.3;
36
+ }
37
+
38
+ .thumbnail.is-active {
39
+ opacity: 1;
40
+ }
41
+
42
+ .thumbnail img {
43
+ width: 100%;
44
+ height: auto;
45
+ }
46
+ `;
@@ -0,0 +1,9 @@
1
+ import PboEditorCardSlider from "./editor-card-slider.component.js";
2
+ export * from "./editor-card-slider.component.js";
3
+ export default PboEditorCardSlider;
4
+
5
+ declare global {
6
+ interface HTMLElementTagNameMap {
7
+ "pbo-image-slider": PboEditorCardSlider;
8
+ }
9
+ }
@@ -0,0 +1,17 @@
1
+ export { default as MessageSelector } from "./message-selector/message-selector.component.js";
2
+ export { default as FabricExample } from "./fabric-example/fabric-example.component.js";
3
+
4
+ export { default as PboSelector } from "./selector/selector.component.js";
5
+ export { default as PboButton } from "./button/button.js";
6
+ export { default as PboButtonGroup } from "./button-group/button-group.js";
7
+ export { default as PboRadioButton } from "./radio-button/radio-button.js";
8
+ export { default as PboRadioGroup } from "./radio-group/radio-group.js";
9
+ export { default as PboTextarea } from "./textarea/textarea.js";
10
+ export { default as PboEditor } from "./editor/editor.js";
11
+ export { default as PboTypeForm } from "./type-form/type-form.js";
12
+ export { default as PboEditorCardSlider } from "./image-slider/editor-card-slider.js";
13
+ export { default as PboCategory } from "./category/category.js";
14
+ export { default as PboDrawer } from "./drawer/drawer.js";
15
+ export { default as PboPageManager } from "./page-manager/page-manager.js";
16
+ export { default as PboCardSelection } from "./card-selection/card-selection.js";
17
+ /* plop:component */
@@ -0,0 +1,154 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { customElement } from "lit/decorators.js";
3
+ import styles from "./message-selector.styles.js";
4
+
5
+ /**
6
+ * A component for selecting messages.
7
+ *
8
+ * @element pairbo-message-selector
9
+ */
10
+ @customElement("pairbo-message-selector")
11
+ export default class PairboMessageSelector extends LitElement {
12
+ static styles = [
13
+ styles,
14
+ css`
15
+ .message-selector {
16
+ text-align: left;
17
+ }
18
+ .message-selector > div {
19
+ margin-bottom: 1rem;
20
+ }
21
+ .message-selector-hidden {
22
+ display: none;
23
+ }
24
+ pre {
25
+ background: #f7f7f7;
26
+ padding: 1rem;
27
+ border: 1px solid #ddd;
28
+ border-radius: 4px;
29
+ overflow-x: auto;
30
+ margin-top: 1rem;
31
+ }
32
+ code {
33
+ font-family: monospace;
34
+ }
35
+ `,
36
+ ];
37
+
38
+ static properties = {
39
+ giftLabel: { type: String },
40
+ premiumLabel: { type: String },
41
+ premiumDescription: { type: String },
42
+ noteLabel: { type: String },
43
+ giftSelected: { type: Boolean },
44
+ premiumSelected: { type: Boolean },
45
+ freeMessageSelected: { type: Boolean },
46
+ };
47
+
48
+ constructor() {
49
+ super();
50
+ // Set default values.
51
+ (this as any).giftLabel = "This is a gift?";
52
+ (this as any).premiumLabel = "Add a premium greeting card";
53
+ (this as any).premiumDescription =
54
+ "Select a premium greeting card and add your personal message. You'll choose from our 100% recycled paper cards, priced at $6, and we'll package it with your gift for that extra thoughtful touch.";
55
+ (this as any).noteLabel = "Add a free message";
56
+ (this as any).giftSelected = false;
57
+ (this as any).premiumSelected = false;
58
+ (this as any).freeMessageSelected = false;
59
+ }
60
+
61
+ public toggleMessageSelector() {
62
+ const messageSelector = this.shadowRoot?.querySelector(".message-selector");
63
+ if (messageSelector) {
64
+ messageSelector.classList.toggle("message-selector-hidden");
65
+ }
66
+ }
67
+
68
+ private _onGiftChange(e: Event) {
69
+ const target = e.target as HTMLInputElement;
70
+ (this as any).giftSelected = target.checked;
71
+ if (!(this as any).giftSelected) {
72
+ // Clear premium and free-message selections if gift is not selected.
73
+ (this as any).premiumSelected = false;
74
+ (this as any).freeMessageSelected = false;
75
+ }
76
+ }
77
+
78
+ private _onPremiumChange(e: Event) {
79
+ const target = e.target as HTMLInputElement;
80
+ if (target.checked) {
81
+ (this as any).premiumSelected = true;
82
+ (this as any).freeMessageSelected = false;
83
+ } else {
84
+ (this as any).premiumSelected = false;
85
+ }
86
+ }
87
+
88
+ private _onFreeMessageChange(e: Event) {
89
+ const target = e.target as HTMLInputElement;
90
+ if (target.checked) {
91
+ (this as any).freeMessageSelected = true;
92
+ (this as any).premiumSelected = false;
93
+ } else {
94
+ (this as any).freeMessageSelected = false;
95
+ }
96
+ }
97
+
98
+ render() {
99
+ return html`
100
+ <div class="message-selector">
101
+ <!-- Gift Checkbox: Always visible -->
102
+ <div>
103
+ <input
104
+ type="checkbox"
105
+ id="is-gift"
106
+ name="is-gift"
107
+ .checked=${(this as any).giftSelected}
108
+ @change=${this._onGiftChange}
109
+ />
110
+ <label for="is-gift">${(this as any).giftLabel}</label>
111
+ </div>
112
+
113
+ <!-- Premium and Free Message Options: Only visible if gift is selected -->
114
+ ${(this as any).giftSelected
115
+ ? html`
116
+ <div>
117
+ <input
118
+ type="checkbox"
119
+ id="premium-card"
120
+ name="premium-card"
121
+ value="premium-card"
122
+ .checked=${(this as any).premiumSelected}
123
+ @change=${this._onPremiumChange}
124
+ />
125
+ <label for="premium-card">${(this as any).premiumLabel}</label>
126
+ <p class="description">${(this as any).premiumDescription}</p>
127
+ </div>
128
+ <div>
129
+ <input
130
+ type="checkbox"
131
+ id="free-message"
132
+ name="free-message"
133
+ value="free-message"
134
+ .checked=${(this as any).freeMessageSelected}
135
+ @change=${this._onFreeMessageChange}
136
+ />
137
+ <label for="free-message">${(this as any).noteLabel}</label>
138
+ </div>
139
+ `
140
+ : null}
141
+
142
+ <!-- Display current selection summary -->
143
+ <div class="current-selection">
144
+ <strong>Current Selection:</strong>
145
+ <ul>
146
+ <li>Gift: ${(this as any).giftSelected ? "Yes" : "No"}</li>
147
+ <li>Premium Card: ${(this as any).premiumSelected ? "Yes" : "No"}</li>
148
+ <li>Free Message: ${(this as any).freeMessageSelected ? "Yes" : "No"}</li>
149
+ </ul>
150
+ </div>
151
+ </div>
152
+ `;
153
+ }
154
+ }
@@ -0,0 +1,16 @@
1
+ // components/message-selector/message-selector.styles.ts
2
+ import { css } from "lit";
3
+
4
+ export default css`
5
+ :host {
6
+ display: block;
7
+ font-family: Arial, sans-serif;
8
+ }
9
+ .message-selector {
10
+ border: 1px solid #ccc;
11
+ padding: 1rem;
12
+ border-radius: 4px;
13
+ background-color: #fff;
14
+ color: black;
15
+ }
16
+ `;
@@ -0,0 +1,64 @@
1
+ // File: components/message-selector/message-selector.test.ts
2
+
3
+ import { fixture, html, expect, elementUpdated } from "@open-wc/testing";
4
+ import type PairboMessageSelector from "./message-selector.js"; // Import the public API for your component
5
+ import sinon from "sinon";
6
+
7
+ describe("<message-selector>", () => {
8
+ let el: PairboMessageSelector;
9
+
10
+ beforeEach(async () => {
11
+ // Create a fixture for the component; this renders it in the test DOM.
12
+ el = await fixture(html`
13
+ <message-selector>
14
+ <!-- Optional: Place some child content if needed -->
15
+ <div>Option 1</div>
16
+ <div>Option 2</div>
17
+ </message-selector>
18
+ `);
19
+ });
20
+
21
+ it("renders the component and its default slot", async () => {
22
+ // Check that the component is defined and has a shadowRoot.
23
+ expect(el).to.exist;
24
+ const slot = el.shadowRoot?.querySelector("slot");
25
+ expect(slot).to.exist;
26
+ });
27
+
28
+ it("passes an accessibility test", async () => {
29
+ await expect(el).to.be.accessible();
30
+ });
31
+
32
+ it("has a default selectedMessage property as an empty string", async () => {
33
+ // Assuming your component defines a reactive property called "selectedMessage"
34
+ // and that its default value is an empty string.
35
+ expect((el as any).selectedMessage).to.equal("");
36
+ });
37
+
38
+ it("updates the selectedMessage property when set", async () => {
39
+ // Simulate setting a new value and wait for the component to update.
40
+ (el as any).selectedMessage = "Hello World";
41
+ await elementUpdated(el);
42
+ expect((el as any).selectedMessage).to.equal("Hello World");
43
+ });
44
+
45
+ // If your component later implements interactions (e.g., clicking on an option sets selectedMessage),
46
+ // you can add tests to simulate those interactions. For example:
47
+ it("updates selectedMessage when a child option is clicked", async () => {
48
+ // For this test, let's assume that clicking on a child element triggers an update.
49
+ // You would implement such logic in your component; here is an example of how to test it.
50
+ const spy = sinon.spy();
51
+ el.addEventListener("selected-change", spy);
52
+
53
+ // Simulate a click on the first child element (adjust according to your component’s behavior)
54
+ const firstOption = el.querySelector("div")!;
55
+ firstOption.click();
56
+ await elementUpdated(el);
57
+
58
+ // In your component, you might update selectedMessage and dispatch a 'selected-change' event.
59
+ // This assertion checks that the event was dispatched.
60
+ expect(spy).to.have.been.called;
61
+ // You can also verify that the property was updated accordingly:
62
+ expect((el as any).selectedMessage).to.equal("Option 1");
63
+ });
64
+ });
@@ -0,0 +1,13 @@
1
+ // components/message-selector/message-selector.ts
2
+ import PairboMessageSelector from "./message-selector.component.js";
3
+
4
+ export * from "./message-selector.component.js";
5
+ export default PairboMessageSelector;
6
+
7
+ // customElements.define("pairbo-message-selector", PairboMessageSelector);
8
+
9
+ declare global {
10
+ interface HTMLElementTagNameMap {
11
+ "pairbo-message-selector": PairboMessageSelector;
12
+ }
13
+ }