@orderlyshop/web-components 0.1.0
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/AGENTS.md +110 -0
- package/README.md +685 -0
- package/bin/orderly-build-category-pages.mjs +160 -0
- package/bin/orderly-generate-category-pages.mjs +308 -0
- package/bin/orderly-hydrate-static-pages.mjs +595 -0
- package/bin/orderly-init-navigation.mjs +327 -0
- package/bin/orderly-init-shop.mjs +876 -0
- package/bin/orderly-init-taxonomy.mjs +2 -0
- package/bin/orderly-publish-site.mjs +342 -0
- package/custom-elements.json +495 -0
- package/dist/browser/orderly-web-components.define.global.js +3085 -0
- package/dist/browser/orderly-web-components.define.global.js.map +1 -0
- package/dist/browser/orderly-web-components.global.js +3085 -0
- package/dist/browser/orderly-web-components.global.js.map +1 -0
- package/dist/default-shop-DWdB_MRd.d.ts +220 -0
- package/dist/default-shop.d.ts +6 -0
- package/dist/default-shop.js +762 -0
- package/dist/default-shop.js.map +1 -0
- package/dist/define-IAQk8OmQ.d.ts +9 -0
- package/dist/define.d.ts +2 -0
- package/dist/define.js +10266 -0
- package/dist/define.js.map +1 -0
- package/dist/index.d.ts +683 -0
- package/dist/index.js +10589 -0
- package/dist/index.js.map +1 -0
- package/dist/navigation.d.ts +51 -0
- package/dist/navigation.js +818 -0
- package/dist/navigation.js.map +1 -0
- package/dist/query.d.ts +31 -0
- package/dist/query.js +115 -0
- package/dist/query.js.map +1 -0
- package/dist/registry-CPDecU3g.d.ts +6 -0
- package/dist/shop-BnT1C6kG.d.ts +173 -0
- package/dist/shop-query.d.ts +8 -0
- package/dist/shop-query.js +100 -0
- package/dist/shop-query.js.map +1 -0
- package/dist/shop.d.ts +8 -0
- package/dist/shop.js +10359 -0
- package/dist/shop.js.map +1 -0
- package/dist/stores.d.ts +46 -0
- package/dist/stores.js +145 -0
- package/dist/stores.js.map +1 -0
- package/dist/taxonomy.d.ts +35 -0
- package/dist/taxonomy.js +247 -0
- package/dist/taxonomy.js.map +1 -0
- package/dist/types-CCQDd6Nd.d.ts +95 -0
- package/docs/components/README.md +610 -0
- package/docs/components/product-grid.md +176 -0
- package/docs/components/product-rail.md +174 -0
- package/examples/shop/README.md +71 -0
- package/examples/shop/package.json +28 -0
- package/examples/shop/src/category.html +20 -0
- package/examples/shop/src/checkout.html +21 -0
- package/examples/shop/src/forretningsbetingelser.html +80 -0
- package/examples/shop/src/includes/body-end.html +1 -0
- package/examples/shop/src/includes/body-start.html +2 -0
- package/examples/shop/src/includes/head.html +32 -0
- package/examples/shop/src/index.html +25 -0
- package/examples/shop/src/navigation.ts +154 -0
- package/examples/shop/src/product.html +24 -0
- package/examples/shop/src/templates/shop-footer.html +76 -0
- package/examples/shop/tsconfig.json +32 -0
- package/examples/shop/vite.config.mjs +184 -0
- package/html-custom-data.json +262 -0
- package/package.json +118 -0
- package/server/README.md +111 -0
- package/server/apache/.htaccess +18 -0
- package/server/nginx/orderly-products.conf +24 -0
- package/server/node/product-snapshot-server.mjs +133 -0
- package/server/php/orderly-product.php +204 -0
|
@@ -0,0 +1,818 @@
|
|
|
1
|
+
// src/utils/dom.ts
|
|
2
|
+
var defaultMobileMediaQuery = "(max-width: 767px)";
|
|
3
|
+
var responsiveTemplateConfig = {
|
|
4
|
+
mobileMediaQuery: defaultMobileMediaQuery
|
|
5
|
+
};
|
|
6
|
+
var responsiveMediaQuery;
|
|
7
|
+
var responsiveListenersConnected = false;
|
|
8
|
+
var responsiveNotificationQueued = false;
|
|
9
|
+
var responsiveTemplateListeners = /* @__PURE__ */ new Set();
|
|
10
|
+
var globalTemplates = [];
|
|
11
|
+
function currentTemplateViewport() {
|
|
12
|
+
if (matchesMedia(responsiveTemplateConfig.mobileMediaQuery)) {
|
|
13
|
+
return "mobile";
|
|
14
|
+
}
|
|
15
|
+
return "desktop";
|
|
16
|
+
}
|
|
17
|
+
function observeResponsiveTemplateChanges(callback) {
|
|
18
|
+
if (typeof window === "undefined") {
|
|
19
|
+
return () => void 0;
|
|
20
|
+
}
|
|
21
|
+
responsiveTemplateListeners.add(callback);
|
|
22
|
+
connectResponsiveListeners();
|
|
23
|
+
return () => {
|
|
24
|
+
responsiveTemplateListeners.delete(callback);
|
|
25
|
+
if (responsiveTemplateListeners.size === 0) {
|
|
26
|
+
disconnectResponsiveListeners();
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function ensureRenderRoot(host) {
|
|
31
|
+
const existing = host.querySelector(":scope > [data-orderly-render-root]");
|
|
32
|
+
if (existing instanceof HTMLElement) {
|
|
33
|
+
return existing;
|
|
34
|
+
}
|
|
35
|
+
const root = document.createElement("div");
|
|
36
|
+
root.dataset.orderlyRenderRoot = "";
|
|
37
|
+
host.append(root);
|
|
38
|
+
return root;
|
|
39
|
+
}
|
|
40
|
+
function render(host, content) {
|
|
41
|
+
host.dataset.orderlyViewport = currentTemplateViewport();
|
|
42
|
+
const root = ensureRenderRoot(host);
|
|
43
|
+
root.dataset.orderlyViewport = currentTemplateViewport();
|
|
44
|
+
root.replaceChildren();
|
|
45
|
+
if (typeof content === "string") {
|
|
46
|
+
root.innerHTML = content;
|
|
47
|
+
} else {
|
|
48
|
+
root.append(content);
|
|
49
|
+
}
|
|
50
|
+
host.dataset.orderlyReady = "true";
|
|
51
|
+
host.setAttribute("data-orderly-ready", "true");
|
|
52
|
+
return root;
|
|
53
|
+
}
|
|
54
|
+
function template(host, name) {
|
|
55
|
+
const localCandidates = [...host.children].filter((element) => element instanceof HTMLTemplateElement && element.dataset.orderlyTemplate === name);
|
|
56
|
+
return selectResponsiveTemplate(localCandidates) ?? selectResponsiveTemplate(globalTemplateCandidates(host, name));
|
|
57
|
+
}
|
|
58
|
+
function cloneTemplate(host, name) {
|
|
59
|
+
const found = template(host, name);
|
|
60
|
+
return found?.content.cloneNode(true);
|
|
61
|
+
}
|
|
62
|
+
function slotTarget(root, name) {
|
|
63
|
+
const target = root.querySelector(`[data-orderly-slot="${name}"], slot[name="${name}"]`);
|
|
64
|
+
return target ?? void 0;
|
|
65
|
+
}
|
|
66
|
+
function replaceSlot(root, name, content) {
|
|
67
|
+
const target = slotTarget(root, name);
|
|
68
|
+
if (!target) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
target.replaceChildren();
|
|
72
|
+
if (typeof content === "string") {
|
|
73
|
+
target.textContent = content;
|
|
74
|
+
} else if (content) {
|
|
75
|
+
target.append(content);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function bindText(root, name, value) {
|
|
79
|
+
root.querySelectorAll(`[data-orderly-bind="${name}"]`).forEach((element) => {
|
|
80
|
+
element.textContent = value ?? "";
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function dispatch(target, type, detail, options = {}) {
|
|
84
|
+
return target.dispatchEvent(new CustomEvent(type, {
|
|
85
|
+
bubbles: true,
|
|
86
|
+
composed: true,
|
|
87
|
+
...options,
|
|
88
|
+
detail
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
function selectResponsiveTemplate(candidates) {
|
|
92
|
+
const viewport = currentTemplateViewport();
|
|
93
|
+
const mediaMatch = candidates.find((candidate) => {
|
|
94
|
+
const media = candidate.dataset.orderlyMedia ?? candidate.getAttribute("media") ?? "";
|
|
95
|
+
return Boolean(media && matchesMedia(media));
|
|
96
|
+
});
|
|
97
|
+
if (mediaMatch) {
|
|
98
|
+
return mediaMatch;
|
|
99
|
+
}
|
|
100
|
+
const viewportMatch = candidates.find((candidate) => normalizeViewport(candidate.dataset.orderlyViewport) === viewport);
|
|
101
|
+
if (viewportMatch) {
|
|
102
|
+
return viewportMatch;
|
|
103
|
+
}
|
|
104
|
+
return candidates.find((candidate) => {
|
|
105
|
+
const media = candidate.dataset.orderlyMedia ?? candidate.getAttribute("media");
|
|
106
|
+
return !media && !candidate.dataset.orderlyViewport;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
function globalTemplateCandidates(host, name) {
|
|
110
|
+
return [
|
|
111
|
+
...globalTemplates,
|
|
112
|
+
...documentGlobalTemplates()
|
|
113
|
+
].filter((candidate) => candidate.dataset.orderlyTemplate === name && templateAppliesToHost(candidate, host));
|
|
114
|
+
}
|
|
115
|
+
function documentGlobalTemplates() {
|
|
116
|
+
if (typeof document === "undefined") {
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
return [...document.querySelectorAll("template[data-orderly-template]")].filter((element) => element instanceof HTMLTemplateElement).filter((element) => element.hasAttribute("data-orderly-for") || element.hasAttribute("data-orderly-component") || element.hasAttribute("data-orderly-template-scope") || element.hasAttribute("data-orderly-global"));
|
|
120
|
+
}
|
|
121
|
+
function templateAppliesToHost(templateElement, host) {
|
|
122
|
+
if (templateElement.hasAttribute("data-orderly-global")) {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
const targets = splitTemplateTargets(
|
|
126
|
+
templateElement.dataset.orderlyFor ?? templateElement.dataset.orderlyComponent ?? templateElement.dataset.orderlyTemplateScope
|
|
127
|
+
);
|
|
128
|
+
if (targets.length === 0) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
const componentName = shortComponentName(host.localName);
|
|
132
|
+
return targets.some((target) => target === "*" || target === host.localName || target === componentName);
|
|
133
|
+
}
|
|
134
|
+
function splitTemplateTargets(value) {
|
|
135
|
+
return (value ?? "").split(/[\s,]+/g).map((target) => target.trim()).filter(Boolean);
|
|
136
|
+
}
|
|
137
|
+
function shortComponentName(localName) {
|
|
138
|
+
return localName.includes("-") ? localName.split("-").slice(1).join("-") : localName;
|
|
139
|
+
}
|
|
140
|
+
function normalizeViewport(value) {
|
|
141
|
+
if (value === "mobile" || value === "desktop") {
|
|
142
|
+
return value;
|
|
143
|
+
}
|
|
144
|
+
return void 0;
|
|
145
|
+
}
|
|
146
|
+
function matchesMedia(media) {
|
|
147
|
+
return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(media).matches;
|
|
148
|
+
}
|
|
149
|
+
function connectResponsiveListeners() {
|
|
150
|
+
if (responsiveListenersConnected || typeof window === "undefined") {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
responsiveListenersConnected = true;
|
|
154
|
+
if (typeof window.matchMedia === "function") {
|
|
155
|
+
responsiveMediaQuery = window.matchMedia(responsiveTemplateConfig.mobileMediaQuery);
|
|
156
|
+
addMediaQueryListener(responsiveMediaQuery, notifyResponsiveTemplateListeners);
|
|
157
|
+
}
|
|
158
|
+
window.addEventListener("resize", notifyResponsiveTemplateListeners);
|
|
159
|
+
}
|
|
160
|
+
function disconnectResponsiveListeners() {
|
|
161
|
+
if (!responsiveListenersConnected || typeof window === "undefined") {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (responsiveMediaQuery) {
|
|
165
|
+
removeMediaQueryListener(responsiveMediaQuery, notifyResponsiveTemplateListeners);
|
|
166
|
+
}
|
|
167
|
+
responsiveMediaQuery = void 0;
|
|
168
|
+
responsiveListenersConnected = false;
|
|
169
|
+
window.removeEventListener("resize", notifyResponsiveTemplateListeners);
|
|
170
|
+
}
|
|
171
|
+
function notifyResponsiveTemplateListeners() {
|
|
172
|
+
if (responsiveNotificationQueued) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
responsiveNotificationQueued = true;
|
|
176
|
+
queueMicrotask(() => {
|
|
177
|
+
responsiveNotificationQueued = false;
|
|
178
|
+
responsiveTemplateListeners.forEach((listener) => listener());
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
function addMediaQueryListener(query, listener) {
|
|
182
|
+
query.addEventListener("change", listener);
|
|
183
|
+
}
|
|
184
|
+
function removeMediaQueryListener(query, listener) {
|
|
185
|
+
query.removeEventListener("change", listener);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// src/i18n.ts
|
|
189
|
+
var UI_TEXTS = {
|
|
190
|
+
DA: {
|
|
191
|
+
addressTitle: "Adresse",
|
|
192
|
+
basketCheckoutDisabledLabel: "L\xE6g varer i kurven f\xF8r betaling",
|
|
193
|
+
basketCheckoutLabel: "G\xE5 til betaling",
|
|
194
|
+
basketEmptyLabel: "Din kurv er tom",
|
|
195
|
+
basketLabel: "Kurv",
|
|
196
|
+
basketPanelTitle: "Kurv",
|
|
197
|
+
categoriesLabel: "Kategorier",
|
|
198
|
+
categoryConfigurationErrorTitle: "Fejl i kategorikonfiguration",
|
|
199
|
+
categoryNoConfigured: "Der er ikke konfigureret nogen kategori.",
|
|
200
|
+
categoryNoDefinitions: "Der er ikke konfigureret nogen navigation.",
|
|
201
|
+
categoryNoSlugMatch: 'Ingen kategori matcher slug "{slug}". Tjek navigation.ts og slug-attributten p\xE5 orderly-category-page.',
|
|
202
|
+
categoryNoUrlMatch: 'Ingen kategori matcher URL-id "{id}". Tjek navigation.ts og #id-v\xE6rdien.',
|
|
203
|
+
checkoutAddressTitle: "Leveringsadresse",
|
|
204
|
+
checkoutCityLabel: "By",
|
|
205
|
+
checkoutCompanyLabel: "Firma",
|
|
206
|
+
checkoutCountryLabel: "Land",
|
|
207
|
+
checkoutCustomerTitle: "Kundeoplysninger",
|
|
208
|
+
checkoutChooseServicePointLabel: "V\xE6lg {method}",
|
|
209
|
+
checkoutDeliveryAddressPrompt: "Udfyld adresse, postnummer og by for at se leveringsmetoder.",
|
|
210
|
+
checkoutDeliveryMethodLabel: "Leveringsmetode",
|
|
211
|
+
checkoutDeliveryTitle: "Leveringsmetode",
|
|
212
|
+
checkoutEmailLabel: "Email",
|
|
213
|
+
checkoutErrorLabel: "Checkout kunne ikke gennemf\xF8res.",
|
|
214
|
+
checkoutFirstNameLabel: "Fornavn",
|
|
215
|
+
checkoutFormTitle: "Levering og kontakt",
|
|
216
|
+
checkoutLastNameLabel: "Efternavn",
|
|
217
|
+
checkoutOrderTitle: "Din ordre",
|
|
218
|
+
checkoutNoDeliveryMethodsLabel: "Der blev ikke fundet leveringsmetoder til adressen.",
|
|
219
|
+
checkoutNoServicePointsLabel: "Der blev ikke fundet udleveringssteder til adressen.",
|
|
220
|
+
checkoutPageDescription: "Udfyld leveringsoplysninger, v\xE6lg levering og gennemf\xF8r din ordre sikkert.",
|
|
221
|
+
checkoutPageTitle: "Levering & betaling",
|
|
222
|
+
checkoutPhoneCountryLabel: "Landekode",
|
|
223
|
+
checkoutPhoneLabel: "Telefon",
|
|
224
|
+
checkoutServicePointLabel: "Udleveringssted",
|
|
225
|
+
checkoutServicePointHelpLabel: "V\xE6lg dit \xF8nskede udleveringssted",
|
|
226
|
+
checkoutStreet2Label: "Adresse 2",
|
|
227
|
+
checkoutStreetLabel: "Adresse",
|
|
228
|
+
checkoutSubmitLabel: "Betal og bestil",
|
|
229
|
+
checkoutSubmittingLabel: "Sender ordre...",
|
|
230
|
+
checkoutTermsLabel: "Jeg accepterer",
|
|
231
|
+
checkoutTermsLinkLabel: "forretningsbetingelserne",
|
|
232
|
+
checkoutZipLabel: "Postnummer",
|
|
233
|
+
clearBasketLabel: "T\xF8m kurv",
|
|
234
|
+
clearSearchLabel: "Ryd s\xF8gning",
|
|
235
|
+
closeLabel: "Luk",
|
|
236
|
+
closeMenuLabel: "Luk menu",
|
|
237
|
+
collapseLabel: "Luk {label}",
|
|
238
|
+
contactTitle: "Kontakt",
|
|
239
|
+
continueShoppingLabel: "Forts\xE6t med at handle",
|
|
240
|
+
deliveryFallbackLabel: "Levering {index}",
|
|
241
|
+
deliveryNote: "Levering beregnes fra valgt leveringsmetode.",
|
|
242
|
+
emailLabel: "Email",
|
|
243
|
+
emptyLabel: "Der blev ikke fundet varer.",
|
|
244
|
+
expandLabel: "\xC5bn {label}",
|
|
245
|
+
homeRailCtaLabel: "Se alle",
|
|
246
|
+
homeTitle: "Butik",
|
|
247
|
+
informationLinksTitle: "Information",
|
|
248
|
+
itemFallbackTitle: "Vare",
|
|
249
|
+
loadMoreLabel: "Indl\xE6s flere",
|
|
250
|
+
loadingLabel: "Indl\xE6ser...",
|
|
251
|
+
mainCategoriesLabel: "Hovedkategorier",
|
|
252
|
+
mainNavigationLabel: "Navigation",
|
|
253
|
+
menuLabel: "Menu",
|
|
254
|
+
navigationItemFallbackLabel: "Punkt {index}",
|
|
255
|
+
openingHoursTitle: "\xC5bningstider",
|
|
256
|
+
phoneLabel: "Telefon",
|
|
257
|
+
productAddLabel: "L\xE6g i kurven",
|
|
258
|
+
productDetailColorLabel: "Farve",
|
|
259
|
+
productDetailConditionLabel: "Stand",
|
|
260
|
+
productDetailSizeLabel: "St\xF8rrelse",
|
|
261
|
+
productErrorLabel: "Produktet kunne ikke indl\xE6ses.",
|
|
262
|
+
productFallbackTitle: "Produkt",
|
|
263
|
+
productImageLabel: "billede {index}",
|
|
264
|
+
productImageOverlayLabel: "Produktbillede",
|
|
265
|
+
productLoadingLabel: "Indl\xE6ser produkt...",
|
|
266
|
+
productNotFoundLabel: "Produktet blev ikke fundet.",
|
|
267
|
+
productOpenImageLabel: "\xC5bn produktbillede i fuld sk\xE6rm",
|
|
268
|
+
productOpenPageLabel: "\xC5bn produktside",
|
|
269
|
+
productRemoveLabel: "Fjern fra kurven",
|
|
270
|
+
productViewLabel: "Vis produkt",
|
|
271
|
+
productViewWithTitle: "Vis {title}",
|
|
272
|
+
productsLabel: "varer",
|
|
273
|
+
productsLoadError: "Varerne kunne ikke indl\xE6ses.",
|
|
274
|
+
quantityLabel: "Antal",
|
|
275
|
+
quantityShortLabel: "Antal",
|
|
276
|
+
removeLabel: "Fjern",
|
|
277
|
+
searchLabel: "S\xF8g",
|
|
278
|
+
searchPlaceholder: "S\xF8g produkter",
|
|
279
|
+
searchPromptLabel: "Skriv i s\xF8gefeltet for at finde varer.",
|
|
280
|
+
searchingLabel: "S\xF8ger efter",
|
|
281
|
+
servicePointFallbackLabel: "Udleveringssted {index}",
|
|
282
|
+
shippingLabel: "Levering",
|
|
283
|
+
shopBrandLabel: "Butik",
|
|
284
|
+
shopNowLabel: "Se varer",
|
|
285
|
+
sortLabel: "Sorter",
|
|
286
|
+
subtotalLabel: "Varer",
|
|
287
|
+
totalLabel: "Total",
|
|
288
|
+
totalNote: "Inkl. moms",
|
|
289
|
+
websiteLabel: "Website"
|
|
290
|
+
},
|
|
291
|
+
EN: {
|
|
292
|
+
addressTitle: "Address",
|
|
293
|
+
basketCheckoutDisabledLabel: "Add items before checkout",
|
|
294
|
+
basketCheckoutLabel: "Go to checkout",
|
|
295
|
+
basketEmptyLabel: "Your basket is empty",
|
|
296
|
+
basketLabel: "Basket",
|
|
297
|
+
basketPanelTitle: "Basket",
|
|
298
|
+
categoriesLabel: "Categories",
|
|
299
|
+
categoryConfigurationErrorTitle: "Category configuration error",
|
|
300
|
+
categoryNoConfigured: "No category has been configured.",
|
|
301
|
+
categoryNoDefinitions: "No navigation definitions have been configured.",
|
|
302
|
+
categoryNoSlugMatch: 'No category matches slug "{slug}". Check navigation.ts and the orderly-category-page slug attribute.',
|
|
303
|
+
categoryNoUrlMatch: 'No category matches URL id "{id}". Check navigation.ts and the #id value.',
|
|
304
|
+
checkoutAddressTitle: "Delivery address",
|
|
305
|
+
checkoutCityLabel: "City",
|
|
306
|
+
checkoutCompanyLabel: "Company",
|
|
307
|
+
checkoutCountryLabel: "Country",
|
|
308
|
+
checkoutCustomerTitle: "Customer information",
|
|
309
|
+
checkoutChooseServicePointLabel: "Choose {method}",
|
|
310
|
+
checkoutDeliveryAddressPrompt: "Enter street, zip, and city to see delivery methods.",
|
|
311
|
+
checkoutDeliveryMethodLabel: "Delivery method",
|
|
312
|
+
checkoutDeliveryTitle: "Delivery method",
|
|
313
|
+
checkoutEmailLabel: "Email",
|
|
314
|
+
checkoutErrorLabel: "Checkout failed.",
|
|
315
|
+
checkoutFirstNameLabel: "First name",
|
|
316
|
+
checkoutFormTitle: "Delivery and contact",
|
|
317
|
+
checkoutLastNameLabel: "Last name",
|
|
318
|
+
checkoutOrderTitle: "Your order",
|
|
319
|
+
checkoutNoDeliveryMethodsLabel: "No delivery methods were found for the address.",
|
|
320
|
+
checkoutNoServicePointsLabel: "No service points were found for the address.",
|
|
321
|
+
checkoutPageDescription: "Enter your delivery details, choose delivery, and complete your order securely.",
|
|
322
|
+
checkoutPageTitle: "Delivery & Payment",
|
|
323
|
+
checkoutPhoneCountryLabel: "Phone country",
|
|
324
|
+
checkoutPhoneLabel: "Phone",
|
|
325
|
+
checkoutServicePointLabel: "Service point",
|
|
326
|
+
checkoutServicePointHelpLabel: "Choose your preferred pickup point",
|
|
327
|
+
checkoutStreet2Label: "Street 2",
|
|
328
|
+
checkoutStreetLabel: "Street",
|
|
329
|
+
checkoutSubmitLabel: "Create order",
|
|
330
|
+
checkoutSubmittingLabel: "Creating order...",
|
|
331
|
+
checkoutTermsLabel: "I accept the terms and conditions",
|
|
332
|
+
checkoutTermsLinkLabel: "terms",
|
|
333
|
+
checkoutZipLabel: "Zip",
|
|
334
|
+
clearBasketLabel: "Clear basket",
|
|
335
|
+
clearSearchLabel: "Clear search",
|
|
336
|
+
closeLabel: "Close",
|
|
337
|
+
closeMenuLabel: "Close menu",
|
|
338
|
+
collapseLabel: "Collapse {label}",
|
|
339
|
+
contactTitle: "Contact",
|
|
340
|
+
continueShoppingLabel: "Continue shopping",
|
|
341
|
+
deliveryFallbackLabel: "Delivery {index}",
|
|
342
|
+
deliveryNote: "Delivery is calculated from the selected delivery method.",
|
|
343
|
+
emailLabel: "Email",
|
|
344
|
+
emptyLabel: "No products found.",
|
|
345
|
+
expandLabel: "Expand {label}",
|
|
346
|
+
homeRailCtaLabel: "See all",
|
|
347
|
+
homeTitle: "Shop",
|
|
348
|
+
informationLinksTitle: "Information",
|
|
349
|
+
itemFallbackTitle: "Item",
|
|
350
|
+
loadMoreLabel: "Load more",
|
|
351
|
+
loadingLabel: "Loading...",
|
|
352
|
+
mainCategoriesLabel: "Main categories",
|
|
353
|
+
mainNavigationLabel: "Main navigation",
|
|
354
|
+
menuLabel: "Menu",
|
|
355
|
+
navigationItemFallbackLabel: "Item {index}",
|
|
356
|
+
openingHoursTitle: "Opening hours",
|
|
357
|
+
phoneLabel: "Phone",
|
|
358
|
+
productAddLabel: "Add to basket",
|
|
359
|
+
productDetailColorLabel: "Color",
|
|
360
|
+
productDetailConditionLabel: "Condition",
|
|
361
|
+
productDetailSizeLabel: "Size",
|
|
362
|
+
productErrorLabel: "Product could not be loaded.",
|
|
363
|
+
productFallbackTitle: "Product",
|
|
364
|
+
productImageLabel: "image {index}",
|
|
365
|
+
productImageOverlayLabel: "Product image",
|
|
366
|
+
productLoadingLabel: "Loading product...",
|
|
367
|
+
productNotFoundLabel: "Product could not be found.",
|
|
368
|
+
productOpenImageLabel: "Open product image fullscreen",
|
|
369
|
+
productOpenPageLabel: "Open product page",
|
|
370
|
+
productRemoveLabel: "Remove from basket",
|
|
371
|
+
productViewLabel: "View product",
|
|
372
|
+
productViewWithTitle: "View {title}",
|
|
373
|
+
productsLabel: "products",
|
|
374
|
+
productsLoadError: "Products could not be loaded.",
|
|
375
|
+
quantityLabel: "Quantity",
|
|
376
|
+
quantityShortLabel: "Qty",
|
|
377
|
+
removeLabel: "Remove",
|
|
378
|
+
searchLabel: "Search",
|
|
379
|
+
searchPlaceholder: "Search products",
|
|
380
|
+
searchPromptLabel: "Start typing to find products.",
|
|
381
|
+
searchingLabel: "Searching for",
|
|
382
|
+
servicePointFallbackLabel: "Service point {index}",
|
|
383
|
+
shippingLabel: "Shipping",
|
|
384
|
+
shopBrandLabel: "Shop",
|
|
385
|
+
shopNowLabel: "Shop now",
|
|
386
|
+
sortLabel: "Sort",
|
|
387
|
+
subtotalLabel: "Items",
|
|
388
|
+
totalLabel: "Total",
|
|
389
|
+
totalNote: "Incl. VAT",
|
|
390
|
+
websiteLabel: "Website"
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
var currentUiLanguage = "DA";
|
|
394
|
+
function uiText(key, language = currentUiLanguage) {
|
|
395
|
+
return UI_TEXTS[language][key] ?? UI_TEXTS.DA[key];
|
|
396
|
+
}
|
|
397
|
+
function formatUiText(key, values, language = currentUiLanguage) {
|
|
398
|
+
return uiText(key, language).replace(/\{(\w+)\}/g, (_match, name) => {
|
|
399
|
+
const value = values[name];
|
|
400
|
+
return value === void 0 ? "" : String(value);
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// src/navigation.ts
|
|
405
|
+
var NavigationController = class extends EventTarget {
|
|
406
|
+
items = [];
|
|
407
|
+
activePath = locationPath();
|
|
408
|
+
expandedIds = /* @__PURE__ */ new Set();
|
|
409
|
+
menuOpen = false;
|
|
410
|
+
setItems(items) {
|
|
411
|
+
this.items = items;
|
|
412
|
+
this.emitChange();
|
|
413
|
+
}
|
|
414
|
+
setActivePath(path) {
|
|
415
|
+
this.activePath = path;
|
|
416
|
+
this.emitChange();
|
|
417
|
+
}
|
|
418
|
+
toggle(id) {
|
|
419
|
+
if (this.expandedIds.has(id)) {
|
|
420
|
+
this.expandedIds.delete(id);
|
|
421
|
+
} else {
|
|
422
|
+
this.expandedIds.add(id);
|
|
423
|
+
}
|
|
424
|
+
this.emitChange();
|
|
425
|
+
}
|
|
426
|
+
closeAll() {
|
|
427
|
+
this.expandedIds.clear();
|
|
428
|
+
this.emitChange();
|
|
429
|
+
}
|
|
430
|
+
openMenu() {
|
|
431
|
+
if (!this.menuOpen) {
|
|
432
|
+
this.menuOpen = true;
|
|
433
|
+
this.emitChange();
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
closeMenu() {
|
|
437
|
+
if (this.menuOpen) {
|
|
438
|
+
this.menuOpen = false;
|
|
439
|
+
this.emitChange();
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
toggleMenu() {
|
|
443
|
+
this.menuOpen = !this.menuOpen;
|
|
444
|
+
this.emitChange();
|
|
445
|
+
}
|
|
446
|
+
select(item) {
|
|
447
|
+
this.dispatchEvent(new CustomEvent("select", {
|
|
448
|
+
detail: { item }
|
|
449
|
+
}));
|
|
450
|
+
}
|
|
451
|
+
isActive(item) {
|
|
452
|
+
return Boolean(item.href && normalizePath(item.href) === normalizePath(this.activePath));
|
|
453
|
+
}
|
|
454
|
+
emitChange() {
|
|
455
|
+
this.dispatchEvent(new Event("change"));
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
var OrderlyNavigationElement = class extends HTMLElement {
|
|
459
|
+
static observedAttributes = ["sticky"];
|
|
460
|
+
controller = new NavigationController();
|
|
461
|
+
menuPanelId = `orderly-navigation-panel-${nextNavigationId()}`;
|
|
462
|
+
disconnectResponsiveTemplates;
|
|
463
|
+
get sticky() {
|
|
464
|
+
return booleanAttribute(this.getAttribute("sticky"), true);
|
|
465
|
+
}
|
|
466
|
+
set sticky(value) {
|
|
467
|
+
if (value) {
|
|
468
|
+
this.removeAttribute("sticky");
|
|
469
|
+
} else {
|
|
470
|
+
this.setAttribute("sticky", "false");
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
connectedCallback() {
|
|
474
|
+
this.disconnectResponsiveTemplates?.();
|
|
475
|
+
this.disconnectResponsiveTemplates = observeResponsiveTemplateChanges(() => this.render());
|
|
476
|
+
this.controller.addEventListener("change", this.onControllerChange);
|
|
477
|
+
this.controller.addEventListener("select", this.onControllerSelect);
|
|
478
|
+
this.controller.setItems(this.getNavigationItems());
|
|
479
|
+
this.addEventListener("click", this.onClick);
|
|
480
|
+
this.addEventListener("keydown", this.onKeyDown);
|
|
481
|
+
this.render();
|
|
482
|
+
}
|
|
483
|
+
attributeChangedCallback() {
|
|
484
|
+
this.updateStickyState();
|
|
485
|
+
if (this.isConnected) {
|
|
486
|
+
this.render();
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
disconnectedCallback() {
|
|
490
|
+
this.controller.removeEventListener("change", this.onControllerChange);
|
|
491
|
+
this.controller.removeEventListener("select", this.onControllerSelect);
|
|
492
|
+
this.removeEventListener("click", this.onClick);
|
|
493
|
+
this.removeEventListener("keydown", this.onKeyDown);
|
|
494
|
+
updateBodyNavigationLock(this, false);
|
|
495
|
+
this.disconnectResponsiveTemplates?.();
|
|
496
|
+
this.disconnectResponsiveTemplates = void 0;
|
|
497
|
+
}
|
|
498
|
+
refresh() {
|
|
499
|
+
this.controller.setItems(this.getNavigationItems());
|
|
500
|
+
}
|
|
501
|
+
closeAll() {
|
|
502
|
+
this.controller.closeAll();
|
|
503
|
+
}
|
|
504
|
+
openMenu() {
|
|
505
|
+
this.controller.openMenu();
|
|
506
|
+
}
|
|
507
|
+
closeMenu() {
|
|
508
|
+
this.controller.closeMenu();
|
|
509
|
+
}
|
|
510
|
+
toggleMenu() {
|
|
511
|
+
this.controller.toggleMenu();
|
|
512
|
+
}
|
|
513
|
+
render() {
|
|
514
|
+
const root = cloneTemplate(this, "navigation") ?? defaultNavigation(this.getAttribute("aria-label") ?? uiText("mainNavigationLabel"));
|
|
515
|
+
this.updateStickyState();
|
|
516
|
+
bindNavigationMenu(root, this.controller, this.menuPanelId, this.sticky);
|
|
517
|
+
replaceSlot(root, "items", renderItems(this.controller, this.controller.items, this));
|
|
518
|
+
render(this, root);
|
|
519
|
+
}
|
|
520
|
+
updateStickyState() {
|
|
521
|
+
this.dataset.orderlyNavigationHost = "";
|
|
522
|
+
this.dataset.orderlySticky = String(this.sticky);
|
|
523
|
+
}
|
|
524
|
+
onControllerChange = () => {
|
|
525
|
+
updateBodyNavigationLock(this, this.controller.menuOpen);
|
|
526
|
+
this.render();
|
|
527
|
+
};
|
|
528
|
+
onControllerSelect = (event) => {
|
|
529
|
+
dispatch(this, "orderly-navigation-select", event.detail);
|
|
530
|
+
};
|
|
531
|
+
onClick = (event) => {
|
|
532
|
+
const target = event.target;
|
|
533
|
+
const menuToggle = target?.closest('[data-orderly-nav-menu-toggle], [data-orderly-action="menu-toggle"]');
|
|
534
|
+
const menuClose = target?.closest('[data-orderly-action="menu-close"]');
|
|
535
|
+
const toggle = target?.closest("[data-orderly-nav-toggle]");
|
|
536
|
+
const link = target?.closest("[data-orderly-nav-id]");
|
|
537
|
+
const parent = target?.closest("[data-orderly-nav-parent]");
|
|
538
|
+
if (menuToggle instanceof HTMLElement) {
|
|
539
|
+
event.preventDefault();
|
|
540
|
+
this.controller.toggleMenu();
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
if (menuClose instanceof HTMLElement) {
|
|
544
|
+
event.preventDefault();
|
|
545
|
+
this.controller.closeMenu();
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
if (toggle instanceof HTMLElement) {
|
|
549
|
+
event.preventDefault();
|
|
550
|
+
this.controller.toggle(toggle.dataset.orderlyNavToggle ?? "");
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
if (link instanceof HTMLElement) {
|
|
554
|
+
const item = findItem(this.controller.items, link.dataset.orderlyNavId ?? "");
|
|
555
|
+
if (item) {
|
|
556
|
+
if (item.children?.length && !this.controller.expandedIds.has(item.id)) {
|
|
557
|
+
event.preventDefault();
|
|
558
|
+
this.controller.toggle(item.id);
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
this.controller.select(item);
|
|
562
|
+
this.controller.closeMenu();
|
|
563
|
+
}
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
if (parent instanceof HTMLElement && target === parent) {
|
|
567
|
+
this.controller.toggle(parent.dataset.orderlyNavParent ?? "");
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
onKeyDown = (event) => {
|
|
571
|
+
if (event.key === "Escape") {
|
|
572
|
+
this.controller.closeAll();
|
|
573
|
+
this.controller.closeMenu();
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
};
|
|
577
|
+
var OrderlyNavigationMenuElement = class extends OrderlyNavigationElement {
|
|
578
|
+
items = [];
|
|
579
|
+
getNavigationItems() {
|
|
580
|
+
return this.items;
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
function navigationItemsFromUIMenu(menus) {
|
|
584
|
+
return menus.map((menu, index) => {
|
|
585
|
+
const label = menu.Link?.DisplayName ?? menu.Link?.URL ?? formatUiText("navigationItemFallbackLabel", { index: index + 1 });
|
|
586
|
+
return {
|
|
587
|
+
id: menu.Link?.URL ?? `${index}`,
|
|
588
|
+
label,
|
|
589
|
+
href: menu.Link?.URL,
|
|
590
|
+
menu,
|
|
591
|
+
children: navigationItemsFromUIMenu(menu.Children)
|
|
592
|
+
};
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
function navigationItemsFromWebsitePages(pages) {
|
|
596
|
+
return pages.map((page) => ({
|
|
597
|
+
id: page.Id?.Id?.Value ?? page.Path,
|
|
598
|
+
label: page.DisplayName,
|
|
599
|
+
href: page.Path,
|
|
600
|
+
page
|
|
601
|
+
}));
|
|
602
|
+
}
|
|
603
|
+
function renderItems(controller, items, host, listId) {
|
|
604
|
+
const list = document.createElement("ul");
|
|
605
|
+
list.className = "orderly-navigation__list";
|
|
606
|
+
if (listId) {
|
|
607
|
+
list.id = listId;
|
|
608
|
+
}
|
|
609
|
+
for (const item of items) {
|
|
610
|
+
const custom = cloneTemplate(host, "item");
|
|
611
|
+
if (custom) {
|
|
612
|
+
bindNavigationItem(custom, controller, item, host);
|
|
613
|
+
list.append(custom);
|
|
614
|
+
continue;
|
|
615
|
+
}
|
|
616
|
+
const element = document.createElement("li");
|
|
617
|
+
element.className = "orderly-navigation__item";
|
|
618
|
+
element.dataset.orderlyItem = item.id;
|
|
619
|
+
const link = document.createElement("a");
|
|
620
|
+
link.className = "orderly-navigation__link";
|
|
621
|
+
link.dataset.orderlyNavId = item.id;
|
|
622
|
+
link.textContent = item.label;
|
|
623
|
+
link.href = item.href ?? "#";
|
|
624
|
+
if (item.target) {
|
|
625
|
+
link.target = item.target;
|
|
626
|
+
}
|
|
627
|
+
if (controller.isActive(item)) {
|
|
628
|
+
link.setAttribute("aria-current", "page");
|
|
629
|
+
}
|
|
630
|
+
if (item.disabled) {
|
|
631
|
+
link.setAttribute("aria-disabled", "true");
|
|
632
|
+
}
|
|
633
|
+
element.append(link);
|
|
634
|
+
if (item.children?.length) {
|
|
635
|
+
const childListId = `orderly-navigation-children-${safeDomId(item.id)}`;
|
|
636
|
+
element.dataset.orderlyHasChildren = "true";
|
|
637
|
+
element.dataset.orderlyNavParent = item.id;
|
|
638
|
+
const button = document.createElement("button");
|
|
639
|
+
button.className = "orderly-navigation__toggle";
|
|
640
|
+
button.type = "button";
|
|
641
|
+
button.dataset.orderlyNavToggle = item.id;
|
|
642
|
+
button.setAttribute("aria-expanded", String(controller.expandedIds.has(item.id)));
|
|
643
|
+
button.setAttribute("aria-controls", childListId);
|
|
644
|
+
button.setAttribute("aria-label", controller.expandedIds.has(item.id) ? formatUiText("collapseLabel", { label: item.label }) : formatUiText("expandLabel", { label: item.label }));
|
|
645
|
+
button.innerHTML = `
|
|
646
|
+
<svg class="orderly-navigation__chevron" viewBox="0 0 20 20" focusable="false" aria-hidden="true">
|
|
647
|
+
<path d="m7 5 5 5-5 5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
648
|
+
</svg>
|
|
649
|
+
`;
|
|
650
|
+
element.append(button);
|
|
651
|
+
if (controller.expandedIds.has(item.id)) {
|
|
652
|
+
element.append(renderItems(controller, item.children, host, childListId));
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
list.append(element);
|
|
656
|
+
}
|
|
657
|
+
return list;
|
|
658
|
+
}
|
|
659
|
+
function defaultNavigation(label) {
|
|
660
|
+
const fragment = document.createDocumentFragment();
|
|
661
|
+
const nav = document.createElement("nav");
|
|
662
|
+
nav.className = "orderly-navigation";
|
|
663
|
+
nav.setAttribute("aria-label", label);
|
|
664
|
+
nav.innerHTML = `
|
|
665
|
+
<button class="orderly-navigation__menu-button" type="button" data-orderly-action="menu-toggle">
|
|
666
|
+
<span class="orderly-navigation__menu-icon" aria-hidden="true"></span>
|
|
667
|
+
<span class="orderly-navigation__menu-label">${uiText("menuLabel")}</span>
|
|
668
|
+
</button>
|
|
669
|
+
<button class="orderly-navigation__backdrop" type="button" data-orderly-action="menu-close" aria-label="${uiText("closeMenuLabel")}"></button>
|
|
670
|
+
<div class="orderly-navigation__panel" data-orderly-menu-panel>
|
|
671
|
+
<button class="orderly-navigation__close" type="button" data-orderly-action="menu-close" aria-label="${uiText("closeMenuLabel")}">
|
|
672
|
+
<span aria-hidden="true">\xD7</span>
|
|
673
|
+
</button>
|
|
674
|
+
<div data-orderly-slot="items"></div>
|
|
675
|
+
</div>
|
|
676
|
+
`;
|
|
677
|
+
fragment.append(nav);
|
|
678
|
+
return fragment;
|
|
679
|
+
}
|
|
680
|
+
function bindNavigationMenu(root, controller, panelId, sticky) {
|
|
681
|
+
let resolvedPanelId = panelId;
|
|
682
|
+
root.querySelectorAll(".orderly-navigation, [data-orderly-navigation]").forEach((element) => {
|
|
683
|
+
if (element instanceof HTMLElement) {
|
|
684
|
+
element.dataset.orderlyMenuOpen = String(controller.menuOpen);
|
|
685
|
+
element.dataset.orderlySticky = String(sticky);
|
|
686
|
+
}
|
|
687
|
+
});
|
|
688
|
+
root.querySelectorAll("[data-orderly-menu-panel]").forEach((element) => {
|
|
689
|
+
if (element instanceof HTMLElement) {
|
|
690
|
+
element.id ||= panelId;
|
|
691
|
+
resolvedPanelId = element.id;
|
|
692
|
+
element.dataset.orderlyMenuOpen = String(controller.menuOpen);
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
root.querySelectorAll('[data-orderly-nav-menu-toggle], [data-orderly-action="menu-toggle"]').forEach((element) => {
|
|
696
|
+
if (element instanceof HTMLElement) {
|
|
697
|
+
element.dataset.orderlyNavMenuToggle = "";
|
|
698
|
+
element.setAttribute("aria-expanded", String(controller.menuOpen));
|
|
699
|
+
element.setAttribute("aria-controls", resolvedPanelId);
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
function bindNavigationItem(root, controller, item, host) {
|
|
704
|
+
const active = controller.isActive(item);
|
|
705
|
+
bindText(root, "label", item.label);
|
|
706
|
+
root.querySelectorAll("[data-orderly-item]").forEach((element) => {
|
|
707
|
+
if (element instanceof HTMLElement) {
|
|
708
|
+
element.dataset.orderlyItem = item.id;
|
|
709
|
+
element.toggleAttribute("data-orderly-active", active);
|
|
710
|
+
element.toggleAttribute("data-orderly-disabled", Boolean(item.disabled));
|
|
711
|
+
element.toggleAttribute("data-orderly-has-children", Boolean(item.children?.length));
|
|
712
|
+
if (item.children?.length) {
|
|
713
|
+
element.dataset.orderlyNavParent = item.id;
|
|
714
|
+
} else {
|
|
715
|
+
element.removeAttribute("data-orderly-nav-parent");
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
});
|
|
719
|
+
const link = root.querySelector('[data-orderly-action="select"], a');
|
|
720
|
+
if (link instanceof HTMLElement) {
|
|
721
|
+
link.dataset.orderlyNavId = item.id;
|
|
722
|
+
if (link instanceof HTMLAnchorElement) {
|
|
723
|
+
link.href = item.href ?? "#";
|
|
724
|
+
if (item.target) {
|
|
725
|
+
link.target = item.target;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
if (active) {
|
|
729
|
+
link.setAttribute("aria-current", "page");
|
|
730
|
+
} else {
|
|
731
|
+
link.removeAttribute("aria-current");
|
|
732
|
+
}
|
|
733
|
+
if (item.disabled) {
|
|
734
|
+
link.setAttribute("aria-disabled", "true");
|
|
735
|
+
} else {
|
|
736
|
+
link.removeAttribute("aria-disabled");
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
const toggle = root.querySelector('[data-orderly-action="toggle"], button');
|
|
740
|
+
if (toggle instanceof HTMLElement) {
|
|
741
|
+
if (item.children?.length) {
|
|
742
|
+
toggle.hidden = false;
|
|
743
|
+
toggle.dataset.orderlyNavToggle = item.id;
|
|
744
|
+
toggle.setAttribute("aria-expanded", String(controller.expandedIds.has(item.id)));
|
|
745
|
+
toggle.setAttribute("aria-controls", `orderly-navigation-children-${safeDomId(item.id)}`);
|
|
746
|
+
toggle.setAttribute("aria-label", controller.expandedIds.has(item.id) ? formatUiText("collapseLabel", { label: item.label }) : formatUiText("expandLabel", { label: item.label }));
|
|
747
|
+
} else {
|
|
748
|
+
toggle.hidden = true;
|
|
749
|
+
toggle.removeAttribute("data-orderly-nav-toggle");
|
|
750
|
+
toggle.removeAttribute("aria-controls");
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
const children = item.children?.length && controller.expandedIds.has(item.id) ? renderItems(controller, item.children, host, `orderly-navigation-children-${safeDomId(item.id)}`) : void 0;
|
|
754
|
+
replaceSlot(root, "children", children);
|
|
755
|
+
}
|
|
756
|
+
function findItem(items, id) {
|
|
757
|
+
for (const item of items) {
|
|
758
|
+
if (item.id === id) {
|
|
759
|
+
return item;
|
|
760
|
+
}
|
|
761
|
+
const child = item.children ? findItem(item.children, id) : void 0;
|
|
762
|
+
if (child) {
|
|
763
|
+
return child;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
return void 0;
|
|
767
|
+
}
|
|
768
|
+
function normalizePath(path) {
|
|
769
|
+
try {
|
|
770
|
+
const url = new URL(path, "https://orderly.local");
|
|
771
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
772
|
+
} catch {
|
|
773
|
+
return path;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
function locationPath() {
|
|
777
|
+
try {
|
|
778
|
+
const current = globalThis.location;
|
|
779
|
+
return current ? `${current.pathname}${current.search}${current.hash}` : "/";
|
|
780
|
+
} catch {
|
|
781
|
+
return "/";
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
function booleanAttribute(value, fallback) {
|
|
785
|
+
if (value === null) {
|
|
786
|
+
return fallback;
|
|
787
|
+
}
|
|
788
|
+
const normalized = value.trim().toLowerCase();
|
|
789
|
+
return normalized !== "false" && normalized !== "0" && normalized !== "off";
|
|
790
|
+
}
|
|
791
|
+
var navigationId = 0;
|
|
792
|
+
var openNavigationMenus = /* @__PURE__ */ new Set();
|
|
793
|
+
function nextNavigationId() {
|
|
794
|
+
navigationId += 1;
|
|
795
|
+
return navigationId;
|
|
796
|
+
}
|
|
797
|
+
function safeDomId(value) {
|
|
798
|
+
return value.replace(/[^a-zA-Z0-9_-]+/g, "-");
|
|
799
|
+
}
|
|
800
|
+
function updateBodyNavigationLock(host, open) {
|
|
801
|
+
if (typeof document === "undefined") {
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
if (open) {
|
|
805
|
+
openNavigationMenus.add(host);
|
|
806
|
+
} else {
|
|
807
|
+
openNavigationMenus.delete(host);
|
|
808
|
+
}
|
|
809
|
+
document.body?.classList.toggle("orderly-navigation-menu-open", openNavigationMenus.size > 0);
|
|
810
|
+
}
|
|
811
|
+
export {
|
|
812
|
+
NavigationController,
|
|
813
|
+
OrderlyNavigationElement,
|
|
814
|
+
OrderlyNavigationMenuElement,
|
|
815
|
+
navigationItemsFromUIMenu,
|
|
816
|
+
navigationItemsFromWebsitePages
|
|
817
|
+
};
|
|
818
|
+
//# sourceMappingURL=navigation.js.map
|