@webround/core 0.1.8 → 0.3.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/dist/base-css.d.ts +8 -0
- package/dist/base-css.js +19 -0
- package/dist/components/WrAltcha.d.ts +5 -0
- package/dist/components/WrAltcha.js +7 -0
- package/dist/components/WrButton.js +19 -0
- package/dist/components/WrForm.d.ts +7 -0
- package/dist/components/WrForm.js +15 -0
- package/dist/components/WrFormPrivacy.d.ts +4 -0
- package/dist/components/WrFormPrivacy.js +6 -0
- package/dist/components/WrFormSuccess.d.ts +4 -0
- package/dist/components/WrFormSuccess.js +6 -0
- package/dist/components/WrIframe.d.ts +8 -0
- package/dist/components/WrIframe.js +13 -0
- package/dist/components/WrImage.d.ts +9 -0
- package/dist/components/WrImage.js +13 -0
- package/dist/components/WrInput.d.ts +8 -0
- package/dist/components/WrInput.js +10 -0
- package/dist/components/WrLangSelector.d.ts +17 -0
- package/dist/components/WrLangSelector.js +27 -0
- package/dist/components/WrLangSync.d.ts +6 -0
- package/dist/components/WrLangSync.js +12 -0
- package/dist/components/WrLink.js +23 -0
- package/dist/components/WrNav.d.ts +26 -0
- package/dist/components/WrNav.js +15 -0
- package/dist/{WrSection.d.ts → components/WrSection.d.ts} +3 -3
- package/dist/components/WrShared.d.ts +22 -0
- package/dist/components/WrShared.js +18 -0
- package/dist/components/WrText.d.ts +11 -0
- package/dist/components/WrText.js +14 -0
- package/dist/components/WrThemeToggle.d.ts +9 -0
- package/dist/components/WrThemeToggle.js +43 -0
- package/dist/components/WrVideo.js +61 -0
- package/dist/context/WrAppContext.d.ts +40 -0
- package/dist/context/WrAppContext.js +95 -0
- package/dist/context/WrLayout.d.ts +23 -0
- package/dist/context/WrLayout.js +18 -0
- package/dist/context/WrPageContext.d.ts +10 -0
- package/dist/context/WrPageContext.js +13 -0
- package/dist/form-react.d.ts +82 -0
- package/dist/form-react.js +165 -0
- package/dist/form.d.ts +83 -0
- package/dist/form.js +175 -0
- package/dist/index.css +651 -0
- package/dist/index.d.ts +20 -8
- package/dist/index.js +20 -8
- package/dist/kinds.d.ts +109 -0
- package/dist/kinds.js +35 -0
- package/dist/lang-codes.d.ts +366 -0
- package/dist/lang-codes.js +166 -0
- package/dist/localized.d.ts +36 -0
- package/dist/localized.js +71 -0
- package/dist/not-found.d.ts +9 -0
- package/dist/not-found.js +13 -0
- package/dist/routing.d.ts +122 -0
- package/dist/routing.js +198 -0
- package/dist/seo-react.d.ts +20 -0
- package/dist/seo-react.js +37 -0
- package/dist/seo.d.ts +167 -0
- package/dist/seo.js +221 -0
- package/dist/site-env.d.ts +25 -0
- package/dist/site-env.js +37 -0
- package/dist/style.d.ts +456 -0
- package/dist/style.js +1081 -0
- package/dist/text-react.d.ts +11 -0
- package/dist/text-react.js +5 -0
- package/dist/theme.d.ts +22 -0
- package/dist/theme.js +45 -0
- package/dist/types.d.ts +37 -21
- package/package.json +93 -7
- package/dist/WrButton.d.ts.map +0 -1
- package/dist/WrButton.js +0 -7
- package/dist/WrButton.js.map +0 -1
- package/dist/WrImage.d.ts +0 -8
- package/dist/WrImage.d.ts.map +0 -1
- package/dist/WrImage.js +0 -7
- package/dist/WrImage.js.map +0 -1
- package/dist/WrLink.d.ts.map +0 -1
- package/dist/WrLink.js +0 -15
- package/dist/WrLink.js.map +0 -1
- package/dist/WrPageContext.d.ts +0 -8
- package/dist/WrPageContext.d.ts.map +0 -1
- package/dist/WrPageContext.js +0 -11
- package/dist/WrPageContext.js.map +0 -1
- package/dist/WrSection.d.ts.map +0 -1
- package/dist/WrSection.js.map +0 -1
- package/dist/WrText.d.ts +0 -11
- package/dist/WrText.d.ts.map +0 -1
- package/dist/WrText.js +0 -7
- package/dist/WrText.js.map +0 -1
- package/dist/WrVideo.d.ts.map +0 -1
- package/dist/WrVideo.js +0 -42
- package/dist/WrVideo.js.map +0 -1
- package/dist/bridge.d.ts +0 -2
- package/dist/bridge.d.ts.map +0 -1
- package/dist/bridge.js +0 -110
- package/dist/bridge.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- /package/dist/{WrButton.d.ts → components/WrButton.d.ts} +0 -0
- /package/dist/{WrLink.d.ts → components/WrLink.d.ts} +0 -0
- /package/dist/{WrSection.js → components/WrSection.js} +0 -0
- /package/dist/{WrVideo.d.ts → components/WrVideo.d.ts} +0 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The few rules every Webround site gets. The first sits under its own classes (a layer below Tailwind's utilities), so any `w-*` (or anything else a person writes) wins. Today:
|
|
3
|
+
* a text fills the box that holds it (`width: 100%`, never wider than it). Without it a text in a flex row takes the width of its words and does not follow the box when the box is
|
|
4
|
+
* resized. The editor puts it in the head of the page (`wrHeadPlugin`), so every site has it, new or old; the text editor's own wrapper (`data-wr-editing`) wears it too, so a
|
|
5
|
+
* text does not change size when it is edited.
|
|
6
|
+
*/
|
|
7
|
+
export declare const WR_BASE_CSS: string;
|
|
8
|
+
//# sourceMappingURL=base-css.d.ts.map
|
package/dist/base-css.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The few rules every Webround site gets. The first sits under its own classes (a layer below Tailwind's utilities), so any `w-*` (or anything else a person writes) wins. Today:
|
|
3
|
+
* a text fills the box that holds it (`width: 100%`, never wider than it). Without it a text in a flex row takes the width of its words and does not follow the box when the box is
|
|
4
|
+
* resized. The editor puts it in the head of the page (`wrHeadPlugin`), so every site has it, new or old; the text editor's own wrapper (`data-wr-editing`) wears it too, so a
|
|
5
|
+
* text does not change size when it is edited.
|
|
6
|
+
*/
|
|
7
|
+
export const WR_BASE_CSS = [
|
|
8
|
+
'@layer base { :where([data-wr-type="text"], [data-wr-editing]) { width: 100%; min-width: 0; } }',
|
|
9
|
+
// The look of a form field that nobody styled: under every class (a layer below the utilities; the attribute selector is stronger than Tailwind's reset of `input`, which is in the same layer), so any `px-*`, `border-*`… a person (or the style panel) writes wins, whatever the order of the CSS
|
|
10
|
+
'@layer base { [data-wr-type="input"] { width: 100%; padding: 0.75rem 1rem; border: 1px solid var(--color-line, #d4d4d8); border-radius: 0.75rem; background: var(--color-page, transparent); color: var(--color-fg, inherit); }',
|
|
11
|
+
' [data-wr-type="input"]::placeholder { color: var(--color-muted, #71717a); }',
|
|
12
|
+
' [data-wr-type="input"]:focus-visible { outline: 2px solid var(--color-accent, currentColor); outline-offset: 1px; } }',
|
|
13
|
+
// A form that went shows its confirmation (a direct child of the form) in place of everything else. NOT in the base layer: a part that has a `flex` of its own would
|
|
14
|
+
// beat a `display: none` there, and the form would stay on screen after it was sent.
|
|
15
|
+
'[data-wr-type="form-success"] { display: none; }',
|
|
16
|
+
'form[data-wr-sent] > [data-wr-type="form-success"] { display: block; }',
|
|
17
|
+
'form[data-wr-sent] > :not([data-wr-type="form-success"]) { display: none; }',
|
|
18
|
+
].join(' ');
|
|
19
|
+
//# sourceMappingURL=base-css.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type WrAltchaViewProps } from '../form-react';
|
|
3
|
+
/** The "I am not a robot" proof of work: put it inside a `WrForm`; the form cannot be sent until it is solved. */
|
|
4
|
+
export declare function WrAltcha(props: WrAltchaViewProps): React.ReactElement | null;
|
|
5
|
+
//# sourceMappingURL=WrAltcha.d.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { WrAltchaView } from '../form-react';
|
|
3
|
+
/** The "I am not a robot" proof of work: put it inside a `WrForm`; the form cannot be sent until it is solved. */
|
|
4
|
+
export function WrAltcha(props) {
|
|
5
|
+
return _jsx(WrAltchaView, { ...props });
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=WrAltcha.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { wrAriaLabel, wrLocalized } from '../localized';
|
|
3
|
+
import { useWrPage } from '../context/WrPageContext';
|
|
4
|
+
import { useWrApp } from '../context/WrAppContext';
|
|
5
|
+
import { useWrSubmitGate } from '../form-react';
|
|
6
|
+
export function WrButton({ id, children, ...props }) {
|
|
7
|
+
const config = useWrPage(id);
|
|
8
|
+
const { lang } = useWrApp();
|
|
9
|
+
const rawContent = config?.content;
|
|
10
|
+
const content = rawContent !== undefined ? (wrLocalized(rawContent, lang) ?? '') : undefined;
|
|
11
|
+
const ariaLabel = wrAriaLabel(config, props['aria-label'], lang);
|
|
12
|
+
// A button that submits a form waits for the form to be ready (the fields, the proof, the consent)
|
|
13
|
+
const gate = useWrSubmitGate();
|
|
14
|
+
const disabled = props.disabled ?? (gate && (props.type ?? 'submit') === 'submit' ? gate.disabled : undefined);
|
|
15
|
+
if (config?.hidden)
|
|
16
|
+
return _jsx(_Fragment, {});
|
|
17
|
+
return (_jsx("button", { "data-wr-id": id, "data-wr-type": "button", ...props, disabled: disabled, "aria-label": ariaLabel, children: content !== undefined ? _jsx("span", { dangerouslySetInnerHTML: { __html: content } }) : children }));
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=WrButton.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type WrFormViewProps } from '../form-react';
|
|
3
|
+
type WrFormProps = Omit<WrFormViewProps, 'lang' | 'config' | 'transport'>;
|
|
4
|
+
/** The published site's form: it sends to the Webround backend (where is in the site's env, see `wrSiteEnv`). */
|
|
5
|
+
export declare function WrForm(props: WrFormProps): React.ReactElement | null;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=WrForm.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { useWrPage } from '../context/WrPageContext';
|
|
4
|
+
import { useWrApp } from '../context/WrAppContext';
|
|
5
|
+
import { wrRealTransport } from '../form';
|
|
6
|
+
import { WrFormView } from '../form-react';
|
|
7
|
+
import { wrSiteEnv } from '../site-env';
|
|
8
|
+
/** The published site's form: it sends to the Webround backend (where is in the site's env, see `wrSiteEnv`). */
|
|
9
|
+
export function WrForm(props) {
|
|
10
|
+
const config = useWrPage(props.id);
|
|
11
|
+
const { lang } = useWrApp();
|
|
12
|
+
const transport = useMemo(() => wrRealTransport(wrSiteEnv()), []);
|
|
13
|
+
return _jsx(WrFormView, { ...props, lang: lang, config: config, transport: transport });
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=WrForm.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface WrIframeOwnProps {
|
|
3
|
+
id: string;
|
|
4
|
+
}
|
|
5
|
+
type WrIframeProps = WrIframeOwnProps & Omit<React.ComponentPropsWithoutRef<'iframe'>, 'id'>;
|
|
6
|
+
export declare function WrIframe({ id, loading, ...props }: WrIframeProps): React.ReactElement;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=WrIframe.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { wrAriaLabel } from '../localized';
|
|
3
|
+
import { useWrApp } from '../context/WrAppContext';
|
|
4
|
+
import { useWrPage } from '../context/WrPageContext';
|
|
5
|
+
export function WrIframe({ id, loading = 'lazy', ...props }) {
|
|
6
|
+
const config = useWrPage(id);
|
|
7
|
+
const { lang } = useWrApp();
|
|
8
|
+
const ariaLabel = wrAriaLabel(config, props['aria-label'], lang);
|
|
9
|
+
if (config?.hidden)
|
|
10
|
+
return _jsx(_Fragment, {});
|
|
11
|
+
return (_jsx("iframe", { loading: loading, "data-wr-id": id, "data-wr-type": "iframe", ...props, "aria-label": ariaLabel }));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=WrIframe.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface WrImageOwnProps {
|
|
3
|
+
id: string;
|
|
4
|
+
objectFit?: React.CSSProperties['objectFit'];
|
|
5
|
+
}
|
|
6
|
+
type WrImageProps = WrImageOwnProps & Omit<React.ComponentPropsWithoutRef<'img'>, 'id'>;
|
|
7
|
+
export declare function WrImage({ id, objectFit, style, alt: codeAlt, ...props }: WrImageProps): React.ReactElement;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=WrImage.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { wrAriaLabel, wrLocalized } from '../localized';
|
|
3
|
+
import { useWrPage } from '../context/WrPageContext';
|
|
4
|
+
import { useWrApp } from '../context/WrAppContext';
|
|
5
|
+
export function WrImage({ id, objectFit, style, alt: codeAlt, ...props }) {
|
|
6
|
+
const config = useWrPage(id);
|
|
7
|
+
const { lang } = useWrApp();
|
|
8
|
+
const ariaLabel = wrAriaLabel(config, props['aria-label'], lang);
|
|
9
|
+
if (config?.hidden)
|
|
10
|
+
return _jsx(_Fragment, {});
|
|
11
|
+
return (_jsx("img", { alt: wrLocalized(config?.alt, lang) ?? codeAlt ?? '', "data-wr-id": id, "data-wr-type": "image", style: { objectFit, ...style }, ...props, "aria-label": ariaLabel }));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=WrImage.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type WrInputViewProps } from '../form-react';
|
|
3
|
+
type WrInputProps = Omit<WrInputViewProps, 'lang' | 'config' | 'type'> & {
|
|
4
|
+
type?: WrInputViewProps['type'];
|
|
5
|
+
};
|
|
6
|
+
export declare function WrInput({ type, ...props }: WrInputProps): React.ReactElement | null;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=WrInput.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useWrPage } from '../context/WrPageContext';
|
|
3
|
+
import { useWrApp } from '../context/WrAppContext';
|
|
4
|
+
import { WrInputView } from '../form-react';
|
|
5
|
+
export function WrInput({ type = 'text', ...props }) {
|
|
6
|
+
const config = useWrPage(props.id);
|
|
7
|
+
const { lang } = useWrApp();
|
|
8
|
+
return _jsx(WrInputView, { ...props, type: type, lang: lang, config: config });
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=WrInput.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type WrLangConfig } from '../i18n/langs';
|
|
3
|
+
interface WrLangOption {
|
|
4
|
+
code: string;
|
|
5
|
+
label: string;
|
|
6
|
+
icon: string;
|
|
7
|
+
active: boolean;
|
|
8
|
+
onSelect: () => void;
|
|
9
|
+
}
|
|
10
|
+
interface WrLangSelectorOwnProps {
|
|
11
|
+
langs: WrLangConfig;
|
|
12
|
+
children?: (opts: WrLangOption[]) => React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
type WrLangSelectorProps = WrLangSelectorOwnProps & Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>;
|
|
15
|
+
export declare function WrLangSelector({ langs, children, ...props }: WrLangSelectorProps): React.ReactElement;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=WrLangSelector.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useNavigate } from 'react-router';
|
|
3
|
+
import { useWrApp } from '../context/WrAppContext';
|
|
4
|
+
import { useWrLangFromPath } from '../hooks/useWrLangFromPath';
|
|
5
|
+
import { buildLangPath } from '../i18n/langs';
|
|
6
|
+
import { langOptions } from '../i18n/lang-code';
|
|
7
|
+
export function WrLangSelector({ langs, children, ...props }) {
|
|
8
|
+
const { lang } = useWrApp();
|
|
9
|
+
const { pageSlug } = useWrLangFromPath(langs);
|
|
10
|
+
const navigate = useNavigate();
|
|
11
|
+
const codes = [langs.default, ...langs.available];
|
|
12
|
+
const options = codes.map(code => {
|
|
13
|
+
const resolvedLang = code === langs.default ? 'default' : code;
|
|
14
|
+
const opt = langOptions[code];
|
|
15
|
+
return {
|
|
16
|
+
code,
|
|
17
|
+
label: opt?.label ?? code,
|
|
18
|
+
icon: opt?.icon ?? '🏳️',
|
|
19
|
+
active: lang === resolvedLang,
|
|
20
|
+
onSelect: () => navigate(buildLangPath(code, pageSlug, langs)),
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
if (children)
|
|
24
|
+
return _jsx(_Fragment, { children: children(options) });
|
|
25
|
+
return (_jsx("div", { "data-wr-type": "lang-selector", ...props, children: options.map(o => (_jsxs("button", { type: "button", "aria-current": o.active ? 'true' : undefined, disabled: o.active, onClick: o.onSelect, children: [_jsx("span", { "aria-hidden": true, children: o.icon }), " ", o.label] }, o.code))) }));
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=WrLangSelector.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { WrLangConfig } from '../i18n/langs';
|
|
2
|
+
/** Tiene WrAppContext.lang sincronizzato col path a ogni navigazione. Va montato dentro WrAppProvider, sopra le route. */
|
|
3
|
+
export declare function WrLangSync({ langs }: {
|
|
4
|
+
langs: WrLangConfig;
|
|
5
|
+
}): null;
|
|
6
|
+
//# sourceMappingURL=WrLangSync.d.ts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// packages/core/src/components/WrLangSync.tsx
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { useWrApp } from '../context/WrAppContext';
|
|
4
|
+
import { useWrLangFromPath } from '../hooks/useWrLangFromPath';
|
|
5
|
+
/** Tiene WrAppContext.lang sincronizzato col path a ogni navigazione. Va montato dentro WrAppProvider, sopra le route. */
|
|
6
|
+
export function WrLangSync({ langs }) {
|
|
7
|
+
const { lang } = useWrLangFromPath(langs);
|
|
8
|
+
const { setLang } = useWrApp();
|
|
9
|
+
useEffect(() => { setLang(lang); }, [lang, setLang]);
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=WrLangSync.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { wrAriaLabel, wrLocalized } from '../localized';
|
|
3
|
+
import { Link } from 'react-router-dom';
|
|
4
|
+
import { useWrPage } from '../context/WrPageContext';
|
|
5
|
+
import { useWrApp } from '../context/WrAppContext';
|
|
6
|
+
import { wrIsExternalHref, wrLocalizeHref } from '../routing';
|
|
7
|
+
export function WrLink({ id, href = '#', children, target, rel, ...props }) {
|
|
8
|
+
const config = useWrPage(id);
|
|
9
|
+
const { lang } = useWrApp();
|
|
10
|
+
const rawContent = config?.content;
|
|
11
|
+
const content = rawContent !== undefined ? (wrLocalized(rawContent, lang) ?? '') : undefined;
|
|
12
|
+
const inner = content !== undefined ? _jsx("span", { dangerouslySetInnerHTML: { __html: content } }) : children;
|
|
13
|
+
const ariaLabel = wrAriaLabel(config, props['aria-label'], lang);
|
|
14
|
+
if (config?.hidden)
|
|
15
|
+
return _jsx(_Fragment, {});
|
|
16
|
+
// An address of the site is a router `Link` and nothing else (a `target` it was given is not used); only one that leaves the site is an `<a>`
|
|
17
|
+
const external = wrIsExternalHref(href);
|
|
18
|
+
if (external) {
|
|
19
|
+
return (_jsx("a", { href: href, target: target, rel: rel, "data-wr-id": id, "data-wr-type": "link", ...props, "aria-label": ariaLabel, children: inner }));
|
|
20
|
+
}
|
|
21
|
+
return (_jsx(Link, { to: wrLocalizeHref(href, lang), "data-wr-id": id, "data-wr-type": "link", ...props, "aria-label": ariaLabel, children: inner }));
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=WrLink.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { WrNavItem } from '../types';
|
|
3
|
+
interface WrNavOwnProps {
|
|
4
|
+
id: string;
|
|
5
|
+
/** What the menu draws: its items, the language, and what the nav was asked to show besides (`accountMenu`: the visitor's account in the header; `cartMenu`: their cart; the site draws both: this package knows nothing of customers). */
|
|
6
|
+
children: (items: WrNavItem[], lang: string, options: WrNavOptions) => React.ReactNode;
|
|
7
|
+
/** The button that switches the site between its light and dark theme (it shows only if the site has a dark theme). */
|
|
8
|
+
themeToggle?: boolean;
|
|
9
|
+
/** The visitor's account in the header (an icon with a sign-in or its shortcuts): the site draws it, this only says whether it is asked for. */
|
|
10
|
+
accountMenu?: boolean;
|
|
11
|
+
/** The visitor's cart in the header (an icon with how many things are in it): the site draws it, this only says whether it is asked for. */
|
|
12
|
+
cartMenu?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* What the nav was asked to show, given to what draws the menu. `ariaLabel` is the name of the menu in the language shown (the editor's, or the `aria-label` written in the code): it goes on the `<nav>` that the
|
|
16
|
+
* menu draws, because on this box (a `div`) a name is ignored by screen readers.
|
|
17
|
+
*/
|
|
18
|
+
export interface WrNavOptions {
|
|
19
|
+
accountMenu: boolean;
|
|
20
|
+
cartMenu: boolean;
|
|
21
|
+
ariaLabel: string | undefined;
|
|
22
|
+
}
|
|
23
|
+
type WrNavProps = WrNavOwnProps & Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>;
|
|
24
|
+
export declare function WrNav({ id, children, themeToggle, accountMenu, cartMenu, ...props }: WrNavProps): React.ReactElement;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=WrNav.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { wrAriaLabel } from '../localized';
|
|
3
|
+
import { useWrPage } from '../context/WrPageContext';
|
|
4
|
+
import { useWrApp } from '../context/WrAppContext';
|
|
5
|
+
import { WrThemeToggle } from './WrThemeToggle';
|
|
6
|
+
export function WrNav({ id, children, themeToggle, accountMenu, cartMenu, ...props }) {
|
|
7
|
+
const config = useWrPage(id);
|
|
8
|
+
const { lang } = useWrApp();
|
|
9
|
+
const items = config?.items ?? [];
|
|
10
|
+
const ariaLabel = wrAriaLabel(config, props['aria-label'], lang);
|
|
11
|
+
if (config?.hidden)
|
|
12
|
+
return _jsx(_Fragment, {});
|
|
13
|
+
return (_jsxs("div", { "data-wr-id": id, "data-wr-type": "nav", ...props, "aria-label": undefined, children: [children(items, lang, { accountMenu: accountMenu === true, cartMenu: cartMenu === true, ariaLabel }), themeToggle && _jsx(WrThemeToggle, {})] }));
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=WrNav.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import type { WrSectionTag } from '../kinds';
|
|
1
2
|
import React from 'react';
|
|
2
|
-
type AllowedTag = 'section' | 'div' | 'article' | 'aside' | 'header' | 'footer' | 'main' | 'nav';
|
|
3
3
|
interface WrSectionOwnProps {
|
|
4
4
|
id: string;
|
|
5
|
-
tag?:
|
|
6
|
-
children
|
|
5
|
+
tag?: WrSectionTag;
|
|
6
|
+
children?: React.ReactNode;
|
|
7
7
|
}
|
|
8
8
|
type WrSectionProps = WrSectionOwnProps & Omit<React.HTMLAttributes<HTMLElement>, 'id'>;
|
|
9
9
|
export declare function WrSection({ id, tag: Tag, children, ...props }: WrSectionProps): React.ReactElement;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ComponentType, type ReactNode } from 'react';
|
|
2
|
+
import type { WrPageConfig } from '../types';
|
|
3
|
+
/** What a shared component needs to read its JSON: the config of every scope, and the provider that hands one to what is inside. */
|
|
4
|
+
export interface WrSharedCtx {
|
|
5
|
+
pageConfigMap: Record<string, WrPageConfig>;
|
|
6
|
+
ScopeProvider: ComponentType<{
|
|
7
|
+
config: WrPageConfig;
|
|
8
|
+
pageName: string;
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
export declare const WrSharedContext: import("react").Context<WrSharedCtx | null>;
|
|
13
|
+
/**
|
|
14
|
+
* The root of a shared component (a card, a banner: anything used on more than one page, like the header and the footer): what is inside
|
|
15
|
+
* reads its values from the component's own JSON, `config/pages/_shared/<name>.json`, whatever page it is on. The component is declared
|
|
16
|
+
* in `src/config/shared.json`. No box of its own.
|
|
17
|
+
*/
|
|
18
|
+
export declare function WrShared({ name, children }: {
|
|
19
|
+
name: string;
|
|
20
|
+
children?: ReactNode;
|
|
21
|
+
}): import("react").JSX.Element;
|
|
22
|
+
//# sourceMappingURL=WrShared.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext } from 'react';
|
|
3
|
+
import { wrSharedName } from '../routing';
|
|
4
|
+
export const WrSharedContext = createContext(null);
|
|
5
|
+
/**
|
|
6
|
+
* The root of a shared component (a card, a banner: anything used on more than one page, like the header and the footer): what is inside
|
|
7
|
+
* reads its values from the component's own JSON, `config/pages/_shared/<name>.json`, whatever page it is on. The component is declared
|
|
8
|
+
* in `src/config/shared.json`. No box of its own.
|
|
9
|
+
*/
|
|
10
|
+
export function WrShared({ name, children }) {
|
|
11
|
+
const shared = useContext(WrSharedContext);
|
|
12
|
+
if (!shared)
|
|
13
|
+
return _jsx(_Fragment, { children: children });
|
|
14
|
+
const scope = wrSharedName(name);
|
|
15
|
+
const { ScopeProvider, pageConfigMap } = shared;
|
|
16
|
+
return _jsx(ScopeProvider, { config: pageConfigMap[scope] ?? {}, pageName: scope, children: children });
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=WrShared.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { WrTextTag } from '../kinds';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
interface WrTextOwnProps {
|
|
4
|
+
id: string;
|
|
5
|
+
tag?: WrTextTag;
|
|
6
|
+
html?: string;
|
|
7
|
+
}
|
|
8
|
+
type WrTextProps = WrTextOwnProps & Omit<React.HTMLAttributes<HTMLElement>, 'id' | 'dangerouslySetInnerHTML'>;
|
|
9
|
+
export declare function WrText({ id, tag, html: fallback, ...props }: WrTextProps): React.JSX.Element;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=WrText.d.ts.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { wrLocalized } from '../localized';
|
|
3
|
+
import { useWrPage } from '../context/WrPageContext';
|
|
4
|
+
import { useWrApp } from '../context/WrAppContext';
|
|
5
|
+
import { WrTextView } from '../text-react';
|
|
6
|
+
export function WrText({ id, tag, html: fallback = '', ...props }) {
|
|
7
|
+
const config = useWrPage(id);
|
|
8
|
+
const { lang } = useWrApp();
|
|
9
|
+
const content = config?.content !== undefined
|
|
10
|
+
? (wrLocalized(config.content, lang) ?? '')
|
|
11
|
+
: fallback;
|
|
12
|
+
return _jsx(WrTextView, { ...props, id: id, tag: tag, html: content });
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=WrText.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* The button that switches a site with two themes between them, and keeps the choice of the visitor (the page starts from it: see `wrThemeStartScript`). It is in `WrNav` when the nav
|
|
4
|
+
* asks for it (`themeToggle`) and it shows only if the site HAS a dark theme: a toggle that does nothing is not drawn.
|
|
5
|
+
*/
|
|
6
|
+
export declare function WrThemeToggle({ className }: {
|
|
7
|
+
className?: string;
|
|
8
|
+
}): React.ReactElement | null;
|
|
9
|
+
//# sourceMappingURL=WrThemeToggle.d.ts.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { WR_THEME_DARK_CLASS, WR_THEME_STORAGE_KEY, wrThemeSiteHasDark } from '../theme';
|
|
4
|
+
import { useWrApp } from '../context/WrAppContext';
|
|
5
|
+
const LABELS = {
|
|
6
|
+
en: { toDark: 'Switch to the dark theme', toLight: 'Switch to the light theme' },
|
|
7
|
+
it: { toDark: 'Attiva il tema scuro', toLight: 'Attiva il tema chiaro' },
|
|
8
|
+
};
|
|
9
|
+
const current = () => (document.documentElement.classList.contains(WR_THEME_DARK_CLASS) ? 'dark' : 'light');
|
|
10
|
+
/**
|
|
11
|
+
* The button that switches a site with two themes between them, and keeps the choice of the visitor (the page starts from it: see `wrThemeStartScript`). It is in `WrNav` when the nav
|
|
12
|
+
* asks for it (`themeToggle`) and it shows only if the site HAS a dark theme: a toggle that does nothing is not drawn.
|
|
13
|
+
*/
|
|
14
|
+
export function WrThemeToggle({ className = '' }) {
|
|
15
|
+
const { lang } = useWrApp();
|
|
16
|
+
const [available, setAvailable] = useState(false);
|
|
17
|
+
const [theme, setTheme] = useState('light');
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
setAvailable(wrThemeSiteHasDark(document));
|
|
20
|
+
setTheme(current());
|
|
21
|
+
// The class can change from elsewhere (another toggle, the code): the button says what is on
|
|
22
|
+
const observer = new MutationObserver(() => setTheme(current()));
|
|
23
|
+
observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });
|
|
24
|
+
// The stylesheet changes while the site is edited (the dark theme is turned on or off): the button is there when it can do something, and only then
|
|
25
|
+
const styles = new MutationObserver(() => setAvailable(wrThemeSiteHasDark(document)));
|
|
26
|
+
styles.observe(document.head, { childList: true, subtree: true, characterData: true, attributes: true });
|
|
27
|
+
return () => { observer.disconnect(); styles.disconnect(); };
|
|
28
|
+
}, []);
|
|
29
|
+
if (!available)
|
|
30
|
+
return null;
|
|
31
|
+
const next = theme === 'dark' ? 'light' : 'dark';
|
|
32
|
+
const labels = LABELS[lang] ?? LABELS.en;
|
|
33
|
+
return (_jsx("button", { type: "button", "data-wr-theme-toggle": "", "aria-label": next === 'dark' ? labels.toDark : labels.toLight, onClick: () => {
|
|
34
|
+
document.documentElement.classList.toggle(WR_THEME_DARK_CLASS, next === 'dark');
|
|
35
|
+
try {
|
|
36
|
+
localStorage.setItem(WR_THEME_STORAGE_KEY, next);
|
|
37
|
+
}
|
|
38
|
+
catch { /* storage blocked: the choice lasts for this visit */ }
|
|
39
|
+
}, className: `inline-flex items-center justify-center size-9 rounded-full opacity-70 hover:opacity-100 hover:bg-current/10 transition ${className}`, children: _jsx("svg", { viewBox: "0 0 24 24", className: "size-5", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: theme === 'dark'
|
|
40
|
+
? _jsxs(_Fragment, { children: [_jsx("circle", { cx: "12", cy: "12", r: "4" }), _jsx("path", { d: "M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41" })] })
|
|
41
|
+
: _jsx("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) }) }));
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=WrThemeToggle.js.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { wrAriaLabel } from '../localized';
|
|
3
|
+
import { useWrApp } from '../context/WrAppContext';
|
|
4
|
+
import { useEffect, useRef } from 'react';
|
|
5
|
+
import { useWrPage } from '../context/WrPageContext';
|
|
6
|
+
function isHlsSrc(src) {
|
|
7
|
+
return src.endsWith('.m3u8') || src.includes('.m3u8?');
|
|
8
|
+
}
|
|
9
|
+
export function WrVideo({ id, src, autoPlay = false, muted = false, loop = false, controls = false, style, ...props }) {
|
|
10
|
+
const config = useWrPage(id);
|
|
11
|
+
const { lang } = useWrApp();
|
|
12
|
+
const ariaLabel = wrAriaLabel(config, props['aria-label'], lang);
|
|
13
|
+
const videoRef = useRef(null);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const video = videoRef.current;
|
|
16
|
+
if (!video || !src)
|
|
17
|
+
return;
|
|
18
|
+
const onEnded = () => {
|
|
19
|
+
if (loop) {
|
|
20
|
+
video.currentTime = 0;
|
|
21
|
+
video.play().catch(() => { });
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
video.addEventListener('ended', onEnded);
|
|
25
|
+
let hlsInstance = null;
|
|
26
|
+
let cancelled = false;
|
|
27
|
+
if (isHlsSrc(src)) {
|
|
28
|
+
import('hls.js').then(({ default: Hls }) => {
|
|
29
|
+
if (cancelled || !video)
|
|
30
|
+
return;
|
|
31
|
+
if (Hls.isSupported()) {
|
|
32
|
+
const hls = new Hls({ enableWorker: true });
|
|
33
|
+
hlsInstance = hls;
|
|
34
|
+
hls.loadSource(src);
|
|
35
|
+
hls.attachMedia(video);
|
|
36
|
+
hls.on(Hls.Events.MANIFEST_PARSED, () => { if (autoPlay)
|
|
37
|
+
video.play().catch(() => { }); });
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
video.src = src;
|
|
41
|
+
if (autoPlay)
|
|
42
|
+
video.play().catch(() => { });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
video.src = src;
|
|
48
|
+
if (autoPlay)
|
|
49
|
+
video.play().catch(() => { });
|
|
50
|
+
}
|
|
51
|
+
return () => {
|
|
52
|
+
cancelled = true;
|
|
53
|
+
hlsInstance?.destroy();
|
|
54
|
+
video.removeEventListener('ended', onEnded);
|
|
55
|
+
};
|
|
56
|
+
}, [src, autoPlay, loop]);
|
|
57
|
+
if (config?.hidden)
|
|
58
|
+
return _jsx(_Fragment, {});
|
|
59
|
+
return (_jsx("video", { ref: videoRef, ...props, muted: muted, controls: controls, "aria-label": ariaLabel, "data-wr-id": id, "data-wr-type": "video", style: style }));
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=WrVideo.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type ComponentType, type ReactNode } from 'react';
|
|
2
|
+
import { type NavigateFunction } from 'react-router-dom';
|
|
3
|
+
import { wrBuildRegistry, wrBuildLazyRegistry, wrBuildPageConfigMap, type WrRoutesFile, type WrLangConfig, type WrSharedFile } from '../routing';
|
|
4
|
+
import type { WrPageConfig } from '../types';
|
|
5
|
+
import { LangCode } from '../lang-codes';
|
|
6
|
+
import type { WrSeoSite } from '../seo';
|
|
7
|
+
export declare function useWrApp(): {
|
|
8
|
+
lang: "default" | "en" | "it" | "id" | "is" | "hr" | "th" | "tr" | "no" | "af" | "am" | "sq" | "ar" | "hy" | "az" | "eu" | "be" | "bn" | "bs" | "bg" | "ca" | "ceb" | "ny" | "zh" | "co" | "cs" | "da" | "nl" | "sjn" | "eo" | "et" | "tl" | "fo" | "fj" | "fi" | "fr" | "fy" | "gl" | "ka" | "de" | "el" | "gu" | "haw" | "ht" | "ha" | "he" | "hi" | "hmn" | "hu" | "ig" | "iu" | "iku" | "ga" | "ja" | "jw" | "kk" | "kn" | "km" | "ko" | "kok" | "ky" | "ku" | "ckb" | "sdh" | "lo" | "lv" | "lt" | "lb" | "mk" | "mg" | "ms" | "ml" | "mt" | "mr" | "mn" | "mi" | "my" | "ne" | "pap" | "fa" | "pl" | "pt" | "pa" | "ps" | "otq" | "ro" | "ru" | "sm" | "gd" | "sr" | "sr-LA" | "sd" | "si" | "sk" | "sl" | "sn" | "st" | "so" | "es" | "su" | "sw" | "sv" | "ty" | "ta" | "tg" | "te" | "bo" | "to" | "uk" | "ur" | "uz" | "vi" | "cy" | "xh" | "yi" | "yo" | "yua" | "yue" | "zu";
|
|
9
|
+
setLang: (lang: LangCode) => void;
|
|
10
|
+
};
|
|
11
|
+
type EagerPageModules = Parameters<typeof wrBuildRegistry>[0];
|
|
12
|
+
type LazyPageModules = Parameters<typeof wrBuildLazyRegistry>[0];
|
|
13
|
+
type PageConfigModules = Parameters<typeof wrBuildPageConfigMap>[0];
|
|
14
|
+
export declare function WrAppProvider({ routesFile, eagerModules, lazyModules, configModules, langs, initialLang, lazyFallback, onRouterReady, PageProvider, Header, Footer, seo, children, }: {
|
|
15
|
+
routesFile: WrRoutesFile;
|
|
16
|
+
eagerModules: EagerPageModules;
|
|
17
|
+
lazyModules: LazyPageModules;
|
|
18
|
+
configModules: PageConfigModules;
|
|
19
|
+
/** Lingue del sito. Se omesso, il routing multilingua è disattivato e lang resta 'default'. */
|
|
20
|
+
langs?: WrLangConfig;
|
|
21
|
+
/** Usato solo come fallback quando `langs` non è passato. */
|
|
22
|
+
initialLang?: LangCode;
|
|
23
|
+
lazyFallback?: ComponentType;
|
|
24
|
+
onRouterReady?: (navigate: NavigateFunction) => void;
|
|
25
|
+
PageProvider?: ComponentType<{
|
|
26
|
+
config: WrPageConfig;
|
|
27
|
+
pageName: string;
|
|
28
|
+
children: ReactNode;
|
|
29
|
+
}>;
|
|
30
|
+
/** Header e footer del sito: su ogni pagina, salvo `header: false` / `footer: false` nella sua voce di routes.json. */
|
|
31
|
+
Header?: ComponentType;
|
|
32
|
+
Footer?: ComponentType;
|
|
33
|
+
/** What is the same for the whole site, for search engines (`config/seo.json`). */
|
|
34
|
+
seo?: WrSeoSite;
|
|
35
|
+
/** The shared components of the site (`config/shared.json`). Only the editor needs it (to know their files): here it is accepted so the same `main.tsx` works with both packages. */
|
|
36
|
+
shared?: WrSharedFile;
|
|
37
|
+
children?: ReactNode;
|
|
38
|
+
}): import("react").JSX.Element;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=WrAppContext.d.ts.map
|