@pure-ds/core 0.6.9 → 0.6.11
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/custom-elements.json +865 -35
- package/dist/types/pds.d.ts +31 -0
- package/dist/types/public/assets/js/pds-manager.d.ts +100 -2
- package/dist/types/public/assets/js/pds-manager.d.ts.map +1 -1
- package/dist/types/public/assets/js/pds.d.ts.map +1 -1
- package/dist/types/public/assets/pds/components/pds-form.d.ts.map +1 -1
- package/dist/types/public/assets/pds/components/pds-live-converter.d.ts +8 -0
- package/dist/types/public/assets/pds/components/pds-live-converter.d.ts.map +1 -0
- package/dist/types/public/assets/pds/components/pds-live-edit.d.ts +1 -195
- package/dist/types/public/assets/pds/components/pds-live-edit.d.ts.map +1 -1
- package/dist/types/public/assets/pds/components/pds-live-importer.d.ts +2 -0
- package/dist/types/public/assets/pds/components/pds-live-importer.d.ts.map +1 -0
- package/dist/types/public/assets/pds/components/pds-live-template-canvas.d.ts +2 -0
- package/dist/types/public/assets/pds/components/pds-live-template-canvas.d.ts.map +1 -0
- package/dist/types/public/assets/pds/components/pds-omnibox.d.ts +0 -2
- package/dist/types/public/assets/pds/components/pds-omnibox.d.ts.map +1 -1
- package/dist/types/public/assets/pds/components/pds-scrollrow.d.ts +20 -0
- package/dist/types/public/assets/pds/components/pds-scrollrow.d.ts.map +1 -1
- package/dist/types/public/assets/pds/components/pds-toaster.d.ts +1 -1
- package/dist/types/public/assets/pds/components/pds-toaster.d.ts.map +1 -1
- package/dist/types/public/assets/pds/components/pds-treeview.d.ts +37 -0
- package/dist/types/public/assets/pds/components/pds-treeview.d.ts.map +1 -0
- package/dist/types/src/js/common/toast.d.ts +8 -0
- package/dist/types/src/js/common/toast.d.ts.map +1 -1
- package/dist/types/src/js/pds-core/pds-config.d.ts +1306 -13
- package/dist/types/src/js/pds-core/pds-config.d.ts.map +1 -1
- package/dist/types/src/js/pds-core/pds-enhancers-meta.d.ts.map +1 -1
- package/dist/types/src/js/pds-core/pds-enhancers.d.ts.map +1 -1
- package/dist/types/src/js/pds-core/pds-generator.d.ts.map +1 -1
- package/dist/types/src/js/pds-core/pds-live.d.ts +2 -1
- package/dist/types/src/js/pds-core/pds-live.d.ts.map +1 -1
- package/dist/types/src/js/pds-core/pds-ontology.d.ts.map +1 -1
- package/dist/types/src/js/pds-core/pds-start-helpers.d.ts +1 -4
- package/dist/types/src/js/pds-core/pds-start-helpers.d.ts.map +1 -1
- package/dist/types/src/js/pds-live-manager/conversion-service.d.ts +66 -0
- package/dist/types/src/js/pds-live-manager/conversion-service.d.ts.map +1 -0
- package/dist/types/src/js/pds-live-manager/import-contract.d.ts +15 -0
- package/dist/types/src/js/pds-live-manager/import-contract.d.ts.map +1 -0
- package/dist/types/src/js/pds-live-manager/import-history-service.d.ts +32 -0
- package/dist/types/src/js/pds-live-manager/import-history-service.d.ts.map +1 -0
- package/dist/types/src/js/pds-live-manager/import-service.d.ts +21 -0
- package/dist/types/src/js/pds-live-manager/import-service.d.ts.map +1 -0
- package/dist/types/src/js/pds-live-manager/template-service.d.ts +17 -0
- package/dist/types/src/js/pds-live-manager/template-service.d.ts.map +1 -0
- package/dist/types/src/js/pds-manager.d.ts +4 -0
- package/dist/types/src/js/pds.d.ts.map +1 -1
- package/package.json +7 -3
- package/packages/pds-cli/README.md +51 -0
- package/packages/pds-cli/bin/pds-import.js +176 -0
- package/packages/pds-cli/bin/pds-static.js +31 -1
- package/packages/pds-cli/bin/postinstall.mjs +17 -8
- package/public/assets/js/app.js +23 -147
- package/public/assets/js/pds-manager.js +481 -248
- package/public/assets/js/pds.js +16 -16
- package/public/assets/pds/components/pds-form.js +124 -27
- package/public/assets/pds/components/pds-live-converter.js +47 -0
- package/public/assets/pds/components/pds-live-edit.js +1626 -211
- package/public/assets/pds/components/pds-live-importer.js +772 -0
- package/public/assets/pds/components/pds-live-template-canvas.js +171 -0
- package/public/assets/pds/components/pds-omnibox.js +146 -20
- package/public/assets/pds/components/pds-scrollrow.js +56 -1
- package/public/assets/pds/components/pds-toaster.js +50 -5
- package/public/assets/pds/components/pds-treeview.js +972 -0
- package/public/assets/pds/custom-elements.json +865 -35
- package/public/assets/pds/pds-css-complete.json +7 -7
- package/public/assets/pds/pds.css-data.json +5 -35
- package/public/assets/pds/templates/commerce-scroll-explorer.html +115 -0
- package/public/assets/pds/templates/content-brand-showcase.html +110 -0
- package/public/assets/pds/templates/feedback-ops-dashboard.html +91 -0
- package/public/assets/pds/templates/release-readiness-radar.html +69 -0
- package/public/assets/pds/templates/support-command-center.html +92 -0
- package/public/assets/pds/templates/templates.json +53 -0
- package/public/assets/pds/templates/workspace-settings-lab.html +131 -0
- package/public/assets/pds/vscode-custom-data.json +54 -4
- package/readme.md +34 -0
- package/src/js/pds-core/pds-config.js +831 -40
- package/src/js/pds-core/pds-enhancers-meta.js +11 -0
- package/src/js/pds-core/pds-enhancers.js +259 -5
- package/src/js/pds-core/pds-generator.js +353 -52
- package/src/js/pds-core/pds-live.js +630 -15
- package/src/js/pds-core/pds-ontology.js +6 -0
- package/src/js/pds-core/pds-start-helpers.js +14 -6
- package/src/js/pds-live-manager/conversion-service.js +3136 -0
- package/src/js/pds-live-manager/import-contract.js +57 -0
- package/src/js/pds-live-manager/import-history-service.js +145 -0
- package/src/js/pds-live-manager/import-service.js +255 -0
- package/src/js/pds-live-manager/tailwind-conversion-rules.json +383 -0
- package/src/js/pds-live-manager/template-service.js +170 -0
- package/src/js/pds.d.ts +31 -0
- package/src/js/pds.js +71 -60
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
const COMPONENT_TAG = "pds-live-template-canvas";
|
|
2
|
+
const PDS = globalThis.PDS;
|
|
3
|
+
|
|
4
|
+
let managerPromise = null;
|
|
5
|
+
|
|
6
|
+
async function getManagerModule() {
|
|
7
|
+
if (managerPromise) return managerPromise;
|
|
8
|
+
managerPromise = (async () => {
|
|
9
|
+
const candidates = [
|
|
10
|
+
PDS?.currentConfig?.managerURL,
|
|
11
|
+
"../core/pds-manager.js",
|
|
12
|
+
"/assets/pds/core/pds-manager.js",
|
|
13
|
+
].filter(Boolean);
|
|
14
|
+
|
|
15
|
+
const attempted = new Set();
|
|
16
|
+
for (const candidate of candidates) {
|
|
17
|
+
try {
|
|
18
|
+
const resolved = new URL(candidate, import.meta.url).href;
|
|
19
|
+
if (attempted.has(resolved)) continue;
|
|
20
|
+
attempted.add(resolved);
|
|
21
|
+
const mod = await import(resolved);
|
|
22
|
+
if (mod && typeof mod === "object") return mod;
|
|
23
|
+
} catch (e) {}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return null;
|
|
27
|
+
})();
|
|
28
|
+
|
|
29
|
+
return managerPromise;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
class PdsLiveTemplateCanvas extends HTMLElement {
|
|
33
|
+
constructor() {
|
|
34
|
+
super();
|
|
35
|
+
this._templates = [];
|
|
36
|
+
this._selectedTemplateId = "";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
connectedCallback() {
|
|
40
|
+
this._renderShell();
|
|
41
|
+
this._loadTemplates();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
_renderShell() {
|
|
45
|
+
this.className = "stack-sm";
|
|
46
|
+
this.innerHTML = `
|
|
47
|
+
<label class="stack-xs">
|
|
48
|
+
<span>Template</span>
|
|
49
|
+
<div class="pds-live-template-omnibox"></div>
|
|
50
|
+
</label>
|
|
51
|
+
<p class="text-muted pds-live-template-description"></p>
|
|
52
|
+
`;
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async _loadTemplates() {
|
|
57
|
+
const manager = await getManagerModule();
|
|
58
|
+
if (typeof manager?.listLiveTemplates !== "function") return;
|
|
59
|
+
|
|
60
|
+
this._templates = (await manager.listLiveTemplates()) || [];
|
|
61
|
+
this._selectedTemplateId = "";
|
|
62
|
+
|
|
63
|
+
const host = this.querySelector(".pds-live-template-omnibox");
|
|
64
|
+
if (!host) return;
|
|
65
|
+
|
|
66
|
+
host.replaceChildren();
|
|
67
|
+
try {
|
|
68
|
+
const omnibox = document.createElement("pds-omnibox");
|
|
69
|
+
omnibox.setAttribute("item-grid", "45px 1fr 0");
|
|
70
|
+
omnibox.setAttribute("placeholder", "Search canvas templates...");
|
|
71
|
+
omnibox.value = "";
|
|
72
|
+
|
|
73
|
+
const templates = this._templates;
|
|
74
|
+
omnibox.settings = {
|
|
75
|
+
hideCategory: true,
|
|
76
|
+
itemGrid: "45px 1fr 0",
|
|
77
|
+
categories: {
|
|
78
|
+
Templates: {
|
|
79
|
+
trigger: () => true,
|
|
80
|
+
getItems: (context = {}) => {
|
|
81
|
+
const query = String(context?.search || "").toLowerCase().trim();
|
|
82
|
+
return templates
|
|
83
|
+
.filter((item) => {
|
|
84
|
+
if (!query) return true;
|
|
85
|
+
const haystack = [item.name, item.description, ...(item.tags || [])]
|
|
86
|
+
.join(" ")
|
|
87
|
+
.toLowerCase();
|
|
88
|
+
return haystack.includes(query);
|
|
89
|
+
})
|
|
90
|
+
.map((item) => ({
|
|
91
|
+
id: item.id,
|
|
92
|
+
text: item.name,
|
|
93
|
+
description: item.description,
|
|
94
|
+
icon: item.icon || "grid-four",
|
|
95
|
+
}));
|
|
96
|
+
},
|
|
97
|
+
action: (selection) => {
|
|
98
|
+
this._selectedTemplateId = selection?.id || "";
|
|
99
|
+
this._updateDescription();
|
|
100
|
+
this._applyTemplate();
|
|
101
|
+
return selection?.id || "";
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
omnibox.addEventListener("result-selected", (event) => {
|
|
108
|
+
const selectedId =
|
|
109
|
+
event?.detail?.id ||
|
|
110
|
+
this._templates.find((item) => item.name === event?.detail?.text)?.id ||
|
|
111
|
+
this._selectedTemplateId;
|
|
112
|
+
if (selectedId) {
|
|
113
|
+
this._selectedTemplateId = selectedId;
|
|
114
|
+
}
|
|
115
|
+
const selected = this._templates.find((item) => item.id === this._selectedTemplateId);
|
|
116
|
+
if (selected?.name) {
|
|
117
|
+
omnibox.value = selected.name;
|
|
118
|
+
}
|
|
119
|
+
this._updateDescription();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
host.appendChild(omnibox);
|
|
123
|
+
} catch (error) {
|
|
124
|
+
const fallback = document.createElement("select");
|
|
125
|
+
fallback.className = "pds-live-template-select";
|
|
126
|
+
this._templates.forEach((template) => {
|
|
127
|
+
const option = document.createElement("option");
|
|
128
|
+
option.value = template.id;
|
|
129
|
+
option.textContent = template.name;
|
|
130
|
+
fallback.appendChild(option);
|
|
131
|
+
});
|
|
132
|
+
fallback.addEventListener("change", () => {
|
|
133
|
+
this._selectedTemplateId = fallback.value;
|
|
134
|
+
this._updateDescription();
|
|
135
|
+
this._applyTemplate();
|
|
136
|
+
});
|
|
137
|
+
host.appendChild(fallback);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
this._updateDescription();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
_updateDescription() {
|
|
144
|
+
const description = this.querySelector(".pds-live-template-description");
|
|
145
|
+
if (!description) return;
|
|
146
|
+
const selected = this._templates.find((item) => item.id === this._selectedTemplateId);
|
|
147
|
+
description.textContent = selected?.description || "";
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async _applyTemplate() {
|
|
151
|
+
if (!this._selectedTemplateId) return;
|
|
152
|
+
|
|
153
|
+
const manager = await getManagerModule();
|
|
154
|
+
if (typeof manager?.runLiveImport !== "function") return;
|
|
155
|
+
|
|
156
|
+
const result = await manager.runLiveImport({
|
|
157
|
+
sourceType: "template",
|
|
158
|
+
templateId: this._selectedTemplateId,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
this.dispatchEvent(
|
|
162
|
+
new CustomEvent("pds:live-template:inject", {
|
|
163
|
+
bubbles: true,
|
|
164
|
+
composed: true,
|
|
165
|
+
detail: { result, templateId: this._selectedTemplateId },
|
|
166
|
+
})
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
customElements.define(COMPONENT_TAG, PdsLiveTemplateCanvas);
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
* @attr {boolean} disabled - Disable the input
|
|
11
11
|
* @attr {boolean} required - Mark the input as required
|
|
12
12
|
* @attr {string} autocomplete - Native autocomplete attribute (default: off)
|
|
13
|
-
* @attr {string} item-grid - Grid template columns for suggestion items
|
|
14
13
|
*
|
|
15
14
|
* @property {Object} settings - AutoComplete settings object (required by consumer)
|
|
16
15
|
*/
|
|
@@ -30,7 +29,6 @@ export class PdsOmnibox extends HTMLElement {
|
|
|
30
29
|
"required",
|
|
31
30
|
"autocomplete",
|
|
32
31
|
"icon",
|
|
33
|
-
"item-grid",
|
|
34
32
|
];
|
|
35
33
|
}
|
|
36
34
|
|
|
@@ -165,15 +163,6 @@ export class PdsOmnibox extends HTMLElement {
|
|
|
165
163
|
else this.setAttribute("icon", value);
|
|
166
164
|
}
|
|
167
165
|
|
|
168
|
-
get itemGrid() {
|
|
169
|
-
return this.getAttribute("item-grid") || "";
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
set itemGrid(value) {
|
|
173
|
-
if (value == null || value === "") this.removeAttribute("item-grid");
|
|
174
|
-
else this.setAttribute("item-grid", value);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
166
|
formAssociatedCallback() {}
|
|
178
167
|
|
|
179
168
|
formDisabledCallback(disabled) {
|
|
@@ -251,7 +240,7 @@ export class PdsOmnibox extends HTMLElement {
|
|
|
251
240
|
--ac-margin: var(--spacing-0);
|
|
252
241
|
--icon-size: var(--spacing-6);
|
|
253
242
|
--ac-itm-height-default: 5rem;
|
|
254
|
-
|
|
243
|
+
--ac-max-height-default: 300px;
|
|
255
244
|
--ac-viewport-gap: var(--spacing-4);
|
|
256
245
|
--ac-suggest-offset: var(--spacing-1);
|
|
257
246
|
}
|
|
@@ -535,9 +524,6 @@ export class PdsOmnibox extends HTMLElement {
|
|
|
535
524
|
if (this.required) this.#input.setAttribute("required", "");
|
|
536
525
|
else this.#input.removeAttribute("required");
|
|
537
526
|
|
|
538
|
-
if (this.itemGrid) this.style.setProperty("--ac-grid", this.itemGrid);
|
|
539
|
-
else this.style.removeProperty("--ac-grid");
|
|
540
|
-
|
|
541
527
|
this.#updateFormValue(this.#input.value);
|
|
542
528
|
}
|
|
543
529
|
|
|
@@ -579,7 +565,8 @@ export class PdsOmnibox extends HTMLElement {
|
|
|
579
565
|
container.style.removeProperty("--ac-color-default");
|
|
580
566
|
container.style.removeProperty("--ac-accent-color");
|
|
581
567
|
|
|
582
|
-
const gridOverride =
|
|
568
|
+
const gridOverride =
|
|
569
|
+
typeof settings.itemGrid === "string" ? settings.itemGrid.trim() : "";
|
|
583
570
|
if (gridOverride) {
|
|
584
571
|
container.style.setProperty("--ac-grid", gridOverride);
|
|
585
572
|
} else if (settings.hideCategory === true) {
|
|
@@ -661,6 +648,8 @@ export class PdsOmnibox extends HTMLElement {
|
|
|
661
648
|
if (!suggestion) return;
|
|
662
649
|
this.#suggestionsObserver = new MutationObserver(() => {
|
|
663
650
|
if (!suggestion.classList.contains("ac-active")) {
|
|
651
|
+
this.removeAttribute("data-suggestions-open");
|
|
652
|
+
this.#clearSuggestionOverlayStyles(suggestion);
|
|
664
653
|
this.#resetIconToDefault();
|
|
665
654
|
}
|
|
666
655
|
});
|
|
@@ -695,6 +684,106 @@ export class PdsOmnibox extends HTMLElement {
|
|
|
695
684
|
this.#autoCompleteViewportHandler = null;
|
|
696
685
|
}
|
|
697
686
|
|
|
687
|
+
#clearSuggestionOverlayStyles(suggestion) {
|
|
688
|
+
if (!suggestion || !suggestion.style) return;
|
|
689
|
+
suggestion.style.removeProperty("position");
|
|
690
|
+
suggestion.style.removeProperty("left");
|
|
691
|
+
suggestion.style.removeProperty("right");
|
|
692
|
+
suggestion.style.removeProperty("top");
|
|
693
|
+
suggestion.style.removeProperty("bottom");
|
|
694
|
+
suggestion.style.removeProperty("width");
|
|
695
|
+
suggestion.style.removeProperty("max-width");
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
#getComposedParent(node) {
|
|
699
|
+
if (!node) return null;
|
|
700
|
+
if (node.parentElement) return node.parentElement;
|
|
701
|
+
const root = node.getRootNode?.();
|
|
702
|
+
if (root && root.host) return root.host;
|
|
703
|
+
return null;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
#hasTransformedAncestor(startNode) {
|
|
707
|
+
let current = startNode;
|
|
708
|
+
let safety = 0;
|
|
709
|
+
while (current && safety < 80) {
|
|
710
|
+
if (current instanceof Element) {
|
|
711
|
+
const style = getComputedStyle(current);
|
|
712
|
+
if (
|
|
713
|
+
style.transform !== "none" ||
|
|
714
|
+
style.perspective !== "none" ||
|
|
715
|
+
style.filter !== "none" ||
|
|
716
|
+
style.backdropFilter !== "none"
|
|
717
|
+
) {
|
|
718
|
+
return true;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
current = this.#getComposedParent(current);
|
|
722
|
+
safety += 1;
|
|
723
|
+
}
|
|
724
|
+
return false;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
#shouldUseFixedSuggestionOverlay(container) {
|
|
728
|
+
if (!container) return false;
|
|
729
|
+
if (this.closest("pds-drawer, dialog")) return false;
|
|
730
|
+
return !this.#hasTransformedAncestor(this);
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
#positionSuggestionInline({ container, suggestion, rect, direction, offset, maxHeight }) {
|
|
734
|
+
if (!container || !suggestion) return;
|
|
735
|
+
this.#clearSuggestionOverlayStyles(suggestion);
|
|
736
|
+
if (direction === "up") {
|
|
737
|
+
suggestion.style.top = "auto";
|
|
738
|
+
suggestion.style.bottom = `${Math.round(rect.height + offset)}px`;
|
|
739
|
+
} else {
|
|
740
|
+
suggestion.style.bottom = "auto";
|
|
741
|
+
suggestion.style.top = `${Math.round(rect.height + offset)}px`;
|
|
742
|
+
}
|
|
743
|
+
container.setAttribute("data-direction", direction);
|
|
744
|
+
suggestion.setAttribute("data-direction", direction);
|
|
745
|
+
container.style.setProperty("--ac-max-height", `${maxHeight}px`);
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
#positionSuggestionOverlay({
|
|
749
|
+
container,
|
|
750
|
+
suggestion,
|
|
751
|
+
rect,
|
|
752
|
+
viewportHeight,
|
|
753
|
+
viewportWidth,
|
|
754
|
+
direction,
|
|
755
|
+
maxHeight,
|
|
756
|
+
gap,
|
|
757
|
+
offset,
|
|
758
|
+
}) {
|
|
759
|
+
if (!container || !suggestion || !suggestion.style) return;
|
|
760
|
+
if (suggestion.classList.contains("full-mobile")) {
|
|
761
|
+
this.#clearSuggestionOverlayStyles(suggestion);
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
const clampedLeft = Math.max(gap, Math.min(rect.left, viewportWidth - rect.width - gap));
|
|
766
|
+
const clampedWidth = Math.max(0, Math.min(rect.width, viewportWidth - gap * 2));
|
|
767
|
+
|
|
768
|
+
suggestion.style.position = "fixed";
|
|
769
|
+
suggestion.style.left = `${Math.round(clampedLeft)}px`;
|
|
770
|
+
suggestion.style.width = `${Math.round(clampedWidth)}px`;
|
|
771
|
+
suggestion.style.maxWidth = `${Math.round(Math.max(0, viewportWidth - gap * 2))}px`;
|
|
772
|
+
suggestion.style.right = "auto";
|
|
773
|
+
|
|
774
|
+
if (direction === "up") {
|
|
775
|
+
suggestion.style.top = "auto";
|
|
776
|
+
suggestion.style.bottom = `${Math.round(viewportHeight - rect.top + offset)}px`;
|
|
777
|
+
} else {
|
|
778
|
+
suggestion.style.bottom = "auto";
|
|
779
|
+
suggestion.style.top = `${Math.round(rect.bottom + offset)}px`;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
container.setAttribute("data-direction", direction);
|
|
783
|
+
suggestion.setAttribute("data-direction", direction);
|
|
784
|
+
container.style.setProperty("--ac-max-height", `${maxHeight}px`);
|
|
785
|
+
}
|
|
786
|
+
|
|
698
787
|
#updateSuggestionMaxHeight() {
|
|
699
788
|
if (!this.#input) return;
|
|
700
789
|
const container = this.#input.parentElement;
|
|
@@ -709,6 +798,7 @@ export class PdsOmnibox extends HTMLElement {
|
|
|
709
798
|
suggestion?.getAttribute("data-direction") ||
|
|
710
799
|
container.getAttribute("data-direction") ||
|
|
711
800
|
"down";
|
|
801
|
+
const offset = this.#readSpacingToken(container, "--ac-suggest-offset") || 0;
|
|
712
802
|
|
|
713
803
|
const availableDown = viewportHeight - rect.bottom - gap;
|
|
714
804
|
const availableUp = rect.top - gap;
|
|
@@ -718,8 +808,6 @@ export class PdsOmnibox extends HTMLElement {
|
|
|
718
808
|
container.setAttribute("data-direction", direction);
|
|
719
809
|
if (suggestion) suggestion.setAttribute("data-direction", direction);
|
|
720
810
|
if (suggestion) {
|
|
721
|
-
const offset =
|
|
722
|
-
this.#readSpacingToken(container, "--ac-suggest-offset") || 0;
|
|
723
811
|
if (direction === "up") {
|
|
724
812
|
suggestion.style.top = "auto";
|
|
725
813
|
suggestion.style.bottom = `${rect.height + offset}px`;
|
|
@@ -732,8 +820,46 @@ export class PdsOmnibox extends HTMLElement {
|
|
|
732
820
|
|
|
733
821
|
const available = direction === "up" ? availableUp : availableDown;
|
|
734
822
|
|
|
735
|
-
const
|
|
823
|
+
const configuredMaxHeight =
|
|
824
|
+
this.#readSpacingToken(container, "--ac-max-height-default") || 200;
|
|
825
|
+
const maxHeight = Math.max(
|
|
826
|
+
0,
|
|
827
|
+
Math.floor(Math.min(available, configuredMaxHeight)),
|
|
828
|
+
);
|
|
736
829
|
container.style.setProperty("--ac-max-height", `${maxHeight}px`);
|
|
830
|
+
|
|
831
|
+
const isSuggestionActive = suggestion?.classList?.contains("ac-active");
|
|
832
|
+
this.toggleAttribute("data-suggestions-open", Boolean(isSuggestionActive));
|
|
833
|
+
|
|
834
|
+
if (!suggestion || !isSuggestionActive || suggestion.classList.contains("full-mobile")) {
|
|
835
|
+
this.#clearSuggestionOverlayStyles(suggestion);
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
if (!this.#shouldUseFixedSuggestionOverlay(container)) {
|
|
840
|
+
this.#positionSuggestionInline({
|
|
841
|
+
container,
|
|
842
|
+
suggestion,
|
|
843
|
+
rect,
|
|
844
|
+
direction,
|
|
845
|
+
offset,
|
|
846
|
+
maxHeight,
|
|
847
|
+
});
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
const viewportWidth = window.visualViewport?.width || window.innerWidth;
|
|
852
|
+
this.#positionSuggestionOverlay({
|
|
853
|
+
container,
|
|
854
|
+
suggestion,
|
|
855
|
+
rect,
|
|
856
|
+
viewportHeight,
|
|
857
|
+
viewportWidth,
|
|
858
|
+
direction,
|
|
859
|
+
maxHeight,
|
|
860
|
+
gap,
|
|
861
|
+
offset,
|
|
862
|
+
});
|
|
737
863
|
}
|
|
738
864
|
|
|
739
865
|
#resolveSuggestionDirection(container) {
|
|
@@ -743,7 +869,7 @@ export class PdsOmnibox extends HTMLElement {
|
|
|
743
869
|
const availableDown = viewportHeight - rect.bottom - gap;
|
|
744
870
|
const availableUp = rect.top - gap;
|
|
745
871
|
const maxDefault =
|
|
746
|
-
this.#readSpacingToken(container, "--ac-max-height-default") ||
|
|
872
|
+
this.#readSpacingToken(container, "--ac-max-height-default") || 200;
|
|
747
873
|
const minDown = Math.min(maxDefault, 180);
|
|
748
874
|
|
|
749
875
|
return availableDown >= minDown || availableDown >= availableUp
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @attr {string} label - Accessible label for the scroll region; also used as fallback heading copy
|
|
13
13
|
* @attr {"start"|"center"} snap - Snap alignment for tiles when scrolling (default: start)
|
|
14
|
+
* @attr {string} tile-min - Minimum tile width (CSS length, e.g. "250px")
|
|
15
|
+
* @attr {string} tile-max - Maximum tile width (CSS length, e.g. "360px")
|
|
14
16
|
*/
|
|
15
17
|
class PdsScrollrow extends HTMLElement {
|
|
16
18
|
#viewport;
|
|
@@ -19,7 +21,7 @@ class PdsScrollrow extends HTMLElement {
|
|
|
19
21
|
#adopted = false;
|
|
20
22
|
|
|
21
23
|
static get observedAttributes() {
|
|
22
|
-
return ["label", "snap"];
|
|
24
|
+
return ["label", "snap", "tile-min", "tile-max"];
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
constructor() {
|
|
@@ -128,6 +130,36 @@ class PdsScrollrow extends HTMLElement {
|
|
|
128
130
|
else this.setAttribute("snap", String(val));
|
|
129
131
|
}
|
|
130
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Minimum tile size applied to slotted content.
|
|
135
|
+
* @returns {string|null}
|
|
136
|
+
*/
|
|
137
|
+
get tileMin() {
|
|
138
|
+
return this.getAttribute("tile-min");
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* @param {string|null} val
|
|
142
|
+
*/
|
|
143
|
+
set tileMin(val) {
|
|
144
|
+
if (val == null) this.removeAttribute("tile-min");
|
|
145
|
+
else this.setAttribute("tile-min", String(val));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Maximum tile size applied to slotted content.
|
|
150
|
+
* @returns {string|null}
|
|
151
|
+
*/
|
|
152
|
+
get tileMax() {
|
|
153
|
+
return this.getAttribute("tile-max");
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* @param {string|null} val
|
|
157
|
+
*/
|
|
158
|
+
set tileMax(val) {
|
|
159
|
+
if (val == null) this.removeAttribute("tile-max");
|
|
160
|
+
else this.setAttribute("tile-max", String(val));
|
|
161
|
+
}
|
|
162
|
+
|
|
131
163
|
/**
|
|
132
164
|
* Lifecycle hook called when the element is inserted into the document.
|
|
133
165
|
*/
|
|
@@ -189,6 +221,11 @@ class PdsScrollrow extends HTMLElement {
|
|
|
189
221
|
this.#applySnap();
|
|
190
222
|
break;
|
|
191
223
|
}
|
|
224
|
+
case "tile-min":
|
|
225
|
+
case "tile-max": {
|
|
226
|
+
this.#applyTileSizing();
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
192
229
|
}
|
|
193
230
|
}
|
|
194
231
|
|
|
@@ -256,6 +293,7 @@ class PdsScrollrow extends HTMLElement {
|
|
|
256
293
|
|
|
257
294
|
// Apply initial snap alignment
|
|
258
295
|
this.#applySnap();
|
|
296
|
+
this.#applyTileSizing();
|
|
259
297
|
|
|
260
298
|
// Observe size changes to refresh controls
|
|
261
299
|
this.#ro = new ResizeObserver(() => this.#updateControls());
|
|
@@ -274,6 +312,23 @@ class PdsScrollrow extends HTMLElement {
|
|
|
274
312
|
}
|
|
275
313
|
}
|
|
276
314
|
|
|
315
|
+
#applyTileSizing() {
|
|
316
|
+
const tileMin = this.tileMin;
|
|
317
|
+
const tileMax = this.tileMax;
|
|
318
|
+
|
|
319
|
+
if (tileMin && String(tileMin).trim()) {
|
|
320
|
+
this.style.setProperty("--tile-min", String(tileMin).trim());
|
|
321
|
+
} else {
|
|
322
|
+
this.style.removeProperty("--tile-min");
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (tileMax && String(tileMax).trim()) {
|
|
326
|
+
this.style.setProperty("--tile-max", String(tileMax).trim());
|
|
327
|
+
} else {
|
|
328
|
+
this.style.removeProperty("--tile-max");
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
277
332
|
/**
|
|
278
333
|
* Scroll the viewport by roughly one page in the indicated direction.
|
|
279
334
|
* @param {Event} e
|
|
@@ -124,6 +124,14 @@ export class AppToaster extends HTMLElement {
|
|
|
124
124
|
white-space: pre-line;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
+
aside.toast .toast-content {
|
|
128
|
+
width: 100%;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
aside.toast .toast-action {
|
|
132
|
+
margin-top: var(--spacing-2);
|
|
133
|
+
}
|
|
134
|
+
|
|
127
135
|
/* Mobile responsive toast positioning */
|
|
128
136
|
@_media (max-width: 640px) {
|
|
129
137
|
:host {
|
|
@@ -182,19 +190,23 @@ export class AppToaster extends HTMLElement {
|
|
|
182
190
|
duration: null, // auto-calculated based on reading time
|
|
183
191
|
closable: true,
|
|
184
192
|
persistent: false, // if true, doesn't auto-dismiss
|
|
193
|
+
html: false,
|
|
194
|
+
action: null,
|
|
185
195
|
};
|
|
186
196
|
|
|
187
197
|
const config = { ...defaults, ...options };
|
|
188
198
|
|
|
189
199
|
// Calculate reading time (average 200 words per minute)
|
|
190
|
-
const
|
|
200
|
+
const messageText = String(message || "");
|
|
201
|
+
const readingText = config.html ? messageText.replace(/<[^>]*>/g, " ") : messageText;
|
|
202
|
+
const wordCount = readingText.split(/\s+/).filter(Boolean).length;
|
|
191
203
|
const baseReadingTime = Math.max(2000, (wordCount / 200) * 60 * 1000); // minimum 2 seconds
|
|
192
204
|
|
|
193
205
|
// Extend time for errors (people need more time to process error messages)
|
|
194
206
|
const multiplier = config.type === "error" ? 1.5 : 1;
|
|
195
207
|
const duration = config.duration || baseReadingTime * multiplier;
|
|
196
208
|
|
|
197
|
-
return this.#showToast(
|
|
209
|
+
return this.#showToast(messageText, config, duration);
|
|
198
210
|
}
|
|
199
211
|
|
|
200
212
|
/*
|
|
@@ -213,7 +225,9 @@ export class AppToaster extends HTMLElement {
|
|
|
213
225
|
config.type,
|
|
214
226
|
config.closable,
|
|
215
227
|
duration,
|
|
216
|
-
config.persistent
|
|
228
|
+
config.persistent,
|
|
229
|
+
config.html,
|
|
230
|
+
config.action
|
|
217
231
|
);
|
|
218
232
|
|
|
219
233
|
// Add to DOM
|
|
@@ -247,7 +261,7 @@ export class AppToaster extends HTMLElement {
|
|
|
247
261
|
* @param {boolean} persistent
|
|
248
262
|
* @returns {HTMLElement}
|
|
249
263
|
*/
|
|
250
|
-
createToastElement(id, message, type, closable, duration, persistent) {
|
|
264
|
+
createToastElement(id, message, type, closable, duration, persistent, html = false, action = null) {
|
|
251
265
|
const toast = document.createElement("aside");
|
|
252
266
|
toast.className = `toast callout ${this.#getAlertClass(type)}`;
|
|
253
267
|
toast.setAttribute("data-toast-id", id);
|
|
@@ -260,6 +274,7 @@ export class AppToaster extends HTMLElement {
|
|
|
260
274
|
icon.setAttribute("size", "lg");
|
|
261
275
|
|
|
262
276
|
const content = document.createElement("div");
|
|
277
|
+
content.className = "toast-content";
|
|
263
278
|
|
|
264
279
|
const title = document.createElement("div");
|
|
265
280
|
title.className = "callout-title";
|
|
@@ -267,11 +282,41 @@ export class AppToaster extends HTMLElement {
|
|
|
267
282
|
|
|
268
283
|
const text = document.createElement("p");
|
|
269
284
|
text.style.margin = "0";
|
|
270
|
-
|
|
285
|
+
if (html) {
|
|
286
|
+
text.innerHTML = String(message || "");
|
|
287
|
+
} else {
|
|
288
|
+
text.textContent = String(message || "");
|
|
289
|
+
}
|
|
271
290
|
|
|
272
291
|
content.appendChild(title);
|
|
273
292
|
content.appendChild(text);
|
|
274
293
|
|
|
294
|
+
if (action && typeof action === "object" && action.label) {
|
|
295
|
+
const actionButton = document.createElement("button");
|
|
296
|
+
actionButton.className = "btn-outline btn-sm toast-action";
|
|
297
|
+
actionButton.type = "button";
|
|
298
|
+
const actionLabel = document.createElement("span");
|
|
299
|
+
actionLabel.textContent = String(action.label);
|
|
300
|
+
|
|
301
|
+
if (action.icon) {
|
|
302
|
+
const icon = document.createElement("pds-icon");
|
|
303
|
+
icon.setAttribute("icon", String(action.icon));
|
|
304
|
+
icon.setAttribute("size", "sm");
|
|
305
|
+
actionButton.appendChild(icon);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
actionButton.appendChild(actionLabel);
|
|
309
|
+
actionButton.addEventListener("click", () => {
|
|
310
|
+
if (typeof action.onClick === "function") {
|
|
311
|
+
action.onClick();
|
|
312
|
+
}
|
|
313
|
+
if (action.dismissOnClick !== false) {
|
|
314
|
+
this.dismissToast(id);
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
content.appendChild(actionButton);
|
|
318
|
+
}
|
|
319
|
+
|
|
275
320
|
toast.appendChild(icon);
|
|
276
321
|
toast.appendChild(content);
|
|
277
322
|
|