tempest-react-sdk 0.73.0 → 0.74.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/README.md +6 -4
- package/dist/br/MapMarkers.cjs +1 -1
- package/dist/br/MapMarkers.cjs.map +1 -1
- package/dist/br/MapMarkers.js +19 -22
- package/dist/br/MapMarkers.js.map +1 -1
- package/dist/components/AIChat/AIChatTurn.cjs +1 -1
- package/dist/components/AIChat/AIChatTurn.cjs.map +1 -1
- package/dist/components/AIChat/AIChatTurn.js +1 -1
- package/dist/components/AIChat/AIChatTurn.js.map +1 -1
- package/dist/components/AppShell/AppShell.module.cjs.map +1 -1
- package/dist/components/AppShell/AppShell.module.js.map +1 -1
- package/dist/components/Button/Button.cjs +1 -1
- package/dist/components/Button/Button.cjs.map +1 -1
- package/dist/components/Button/Button.js +41 -36
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Button/Button.module.cjs.map +1 -1
- package/dist/components/Button/Button.module.js.map +1 -1
- package/dist/components/Button/ButtonContent.cjs +2 -0
- package/dist/components/Button/ButtonContent.cjs.map +1 -0
- package/dist/components/Button/ButtonContent.js +34 -0
- package/dist/components/Button/ButtonContent.js.map +1 -0
- package/dist/components/Button/ButtonSlot.cjs +2 -0
- package/dist/components/Button/ButtonSlot.cjs.map +1 -0
- package/dist/components/Button/ButtonSlot.js +36 -0
- package/dist/components/Button/ButtonSlot.js.map +1 -0
- package/dist/components/Button/button-class.cjs +2 -0
- package/dist/components/Button/button-class.cjs.map +1 -0
- package/dist/components/Button/button-class.js +13 -0
- package/dist/components/Button/button-class.js.map +1 -0
- package/dist/components/Button/link-rel.cjs +2 -0
- package/dist/components/Button/link-rel.cjs.map +1 -0
- package/dist/components/Button/link-rel.js +11 -0
- package/dist/components/Button/link-rel.js.map +1 -0
- package/dist/components/Button/slot.cjs +2 -0
- package/dist/components/Button/slot.cjs.map +1 -0
- package/dist/components/Button/slot.js +41 -0
- package/dist/components/Button/slot.js.map +1 -0
- package/dist/components/Collapsible/Collapsible.cjs +1 -1
- package/dist/components/Collapsible/Collapsible.cjs.map +1 -1
- package/dist/components/Collapsible/Collapsible.js +1 -1
- package/dist/components/Collapsible/Collapsible.js.map +1 -1
- package/dist/components/Form/Form.cjs.map +1 -1
- package/dist/components/Form/Form.js.map +1 -1
- package/dist/components/InstallButton/InstallButton.cjs.map +1 -1
- package/dist/components/InstallButton/InstallButton.js.map +1 -1
- package/dist/components/Modal/Modal.cjs +1 -1
- package/dist/components/Modal/Modal.cjs.map +1 -1
- package/dist/components/Modal/Modal.js +1 -1
- package/dist/components/Modal/Modal.js.map +1 -1
- package/dist/components/Modal/Modal.module.cjs +1 -1
- package/dist/components/Modal/Modal.module.cjs.map +1 -1
- package/dist/components/Modal/Modal.module.js +1 -1
- package/dist/components/Modal/Modal.module.js.map +1 -1
- package/dist/components/Page/Page.cjs +1 -1
- package/dist/components/Page/Page.cjs.map +1 -1
- package/dist/components/Page/Page.js +23 -39
- package/dist/components/Page/Page.js.map +1 -1
- package/dist/components/Page/Page.module.cjs +1 -1
- package/dist/components/Page/Page.module.cjs.map +1 -1
- package/dist/components/Page/Page.module.js +5 -11
- package/dist/components/Page/Page.module.js.map +1 -1
- package/dist/components/Reveal/Reveal.cjs +2 -0
- package/dist/components/Reveal/Reveal.cjs.map +1 -0
- package/dist/components/Reveal/Reveal.js +56 -0
- package/dist/components/Reveal/Reveal.js.map +1 -0
- package/dist/components/Reveal/Reveal.module.cjs +3 -0
- package/dist/components/Reveal/Reveal.module.cjs.map +1 -0
- package/dist/components/Reveal/Reveal.module.js +7 -0
- package/dist/components/Reveal/Reveal.module.js.map +1 -0
- package/dist/components/Reveal/reveal-threshold.cjs +2 -0
- package/dist/components/Reveal/reveal-threshold.cjs.map +1 -0
- package/dist/components/Reveal/reveal-threshold.js +13 -0
- package/dist/components/Reveal/reveal-threshold.js.map +1 -0
- package/dist/components/SectionHeader/SectionHeader.cjs +2 -0
- package/dist/components/SectionHeader/SectionHeader.cjs.map +1 -0
- package/dist/components/SectionHeader/SectionHeader.js +58 -0
- package/dist/components/SectionHeader/SectionHeader.js.map +1 -0
- package/dist/components/SectionHeader/SectionHeader.module.cjs +3 -0
- package/dist/components/SectionHeader/SectionHeader.module.cjs.map +1 -0
- package/dist/components/SectionHeader/SectionHeader.module.js +15 -0
- package/dist/components/SectionHeader/SectionHeader.module.js.map +1 -0
- package/dist/components/Timeline/Timeline.cjs +1 -1
- package/dist/components/Timeline/Timeline.cjs.map +1 -1
- package/dist/components/Timeline/Timeline.js +22 -15
- package/dist/components/Timeline/Timeline.js.map +1 -1
- package/dist/components/Timeline/Timeline.module.cjs +1 -1
- package/dist/components/Timeline/Timeline.module.cjs.map +1 -1
- package/dist/components/Timeline/Timeline.module.js +1 -1
- package/dist/components/Timeline/Timeline.module.js.map +1 -1
- package/dist/styles/Reveal.css +2 -0
- package/dist/styles/SectionHeader.css +2 -0
- package/dist/styles/actions.css +24 -22
- package/dist/styles/base.css +3 -1
- package/dist/styles/component/AppShell.css +1 -1
- package/dist/styles/component/Button.css +24 -22
- package/dist/styles/component/Modal.css +2 -2
- package/dist/styles/component/Page.css +0 -6
- package/dist/styles/component/Reveal.css +9 -0
- package/dist/styles/component/SectionHeader.css +9 -0
- package/dist/styles/component/Timeline.css +5 -5
- package/dist/styles/core.css +3 -1
- package/dist/styles/data.css +5 -5
- package/dist/styles/inverse.css +147 -0
- package/dist/styles/layout.css +9 -7
- package/dist/styles/manifest.json +14 -1
- package/dist/styles/overlay.css +2 -2
- package/dist/styles/utility.css +8 -0
- package/dist/styles.css +1 -1
- package/dist/tempest-react-sdk.cjs +1 -1
- package/dist/tempest-react-sdk.d.ts +353 -4
- package/dist/tempest-react-sdk.js +350 -346
- package/dist/theme/create-theme.cjs +3 -3
- package/dist/theme/create-theme.cjs.map +1 -1
- package/dist/theme/create-theme.js +67 -55
- package/dist/theme/create-theme.js.map +1 -1
- package/dist/theme/inverse-render.cjs +3 -0
- package/dist/theme/inverse-render.cjs.map +1 -0
- package/dist/theme/inverse-render.js +10 -0
- package/dist/theme/inverse-render.js.map +1 -0
- package/dist/theme/inverse-surface.cjs +2 -0
- package/dist/theme/inverse-surface.cjs.map +1 -0
- package/dist/theme/inverse-surface.js +258 -0
- package/dist/theme/inverse-surface.js.map +1 -0
- package/dist/theme/status-tokens.cjs +2 -0
- package/dist/theme/status-tokens.cjs.map +1 -0
- package/dist/theme/status-tokens.js +15 -0
- package/dist/theme/status-tokens.js.map +1 -0
- package/dist/vite/create-vite-config.cjs +1 -1
- package/dist/vite/create-vite-config.cjs.map +1 -1
- package/dist/vite/create-vite-config.js +6 -4
- package/dist/vite/create-vite-config.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstallButton.cjs","names":[],"sources":["../../../src/components/InstallButton/InstallButton.tsx"],"sourcesContent":["import { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Button, type
|
|
1
|
+
{"version":3,"file":"InstallButton.cjs","names":[],"sources":["../../../src/components/InstallButton/InstallButton.tsx"],"sourcesContent":["import { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Button, type ButtonAsButtonProps } from \"@/components/Button\";\nimport { useInstallPrompt } from \"@/hooks/use-install-prompt\";\nimport { cn } from \"@/utils/cn\";\nimport { defaultInstallHint, type RenderInstallHint } from \"./install-hints\";\nimport styles from \"./InstallButton.module.css\";\n\nexport type InstallOutcome = \"accepted\" | \"dismissed\" | \"unsupported\";\n\nexport interface InstallButtonProps extends Omit<ButtonAsButtonProps, \"onClick\" | \"children\"> {\n /** Button label. Default `\"Instalar app\"`. */\n label?: ReactNode;\n /**\n * Label used when the browser cannot be prompted and the button reveals the\n * manual instruction instead. Default `\"Como instalar\"`.\n */\n hintLabel?: ReactNode;\n /** Called with the user's choice after the install prompt resolves. */\n onResult?: (outcome: InstallOutcome) => void;\n /**\n * Replaces the instruction shown for the `\"ios\"` and `\"manual\"` methods.\n *\n * The default copy is in PT-BR and names the real menu entries. Pass this to\n * translate it, to shorten it, or to point at a screenshot of your own.\n */\n renderHint?: RenderInstallHint;\n /**\n * How long, in ms, to wait for `beforeinstallprompt` before falling back to\n * the manual instruction. Forwarded to {@link useInstallPrompt}; defaults to\n * 3000 there.\n */\n manualFallbackDelayMs?: number;\n /** Class applied to the wrapper that holds the button and the instruction. */\n wrapperClassName?: string;\n}\n\n/**\n * Button wired to PWA installation, through {@link useInstallPrompt}.\n *\n * Where the browser fires `beforeinstallprompt`, the click installs. Where it\n * does not — iOS Safari, and the Android Chromium forks (Mi Browser, UC, Opera\n * Mini, Huawei) that strip the API — the click reveals the instruction for that\n * platform instead of the button disappearing.\n *\n * That disappearance was the defect: the component was built on\n * `useBeforeInstallPrompt`, so it rendered `null` exactly where the user needs\n * the most help, and every app re-implemented the iOS and manual paths locally.\n * Nothing renders only when there is genuinely nothing to offer — already\n * installed, running standalone, or inside the decline cooldown.\n *\n * Inherits every {@link Button} prop of the `<button>` mode (`variant`, `size`,\n * `leftIcon`, …) but not `href`: its click opens the install prompt\n * or toggles the instruction, which is an action, not a navigation.\n *\n * @example\n * <InstallButton variant=\"primary\" leftIcon={<Download />} />\n *\n * @example\n * <InstallButton renderHint={({ method }) => (method === \"ios\" ? <IOSSteps /> : <MenuSteps />)} />\n */\nexport function InstallButton({\n label = \"Instalar app\",\n hintLabel = \"Como instalar\",\n onResult,\n renderHint = defaultInstallHint,\n manualFallbackDelayMs,\n wrapperClassName,\n ...props\n}: InstallButtonProps) {\n const { method, openInChromeIntent, install } = useInstallPrompt({ manualFallbackDelayMs });\n const [hintOpen, setHintOpen] = useState(false);\n const hintId = useId();\n\n if (method === \"none\") return null;\n\n if (method === \"native\") {\n return (\n <Button\n onClick={async () => {\n const accepted = await install();\n onResult?.(accepted ? \"accepted\" : \"dismissed\");\n }}\n {...props}\n >\n {label}\n </Button>\n );\n }\n\n const hint = renderHint({ method, openInChromeIntent });\n\n return (\n <div className={cn(styles.wrapper, wrapperClassName)}>\n <Button\n aria-expanded={hintOpen}\n aria-controls={hintOpen && hint ? hintId : undefined}\n onClick={() => setHintOpen((open) => !open)}\n {...props}\n >\n {hintLabel}\n </Button>\n {hintOpen && hint ? (\n <p className={styles.hint} id={hintId}>\n {hint}\n </p>\n ) : null}\n </div>\n );\n}\n"],"mappings":"uPA6DA,SAAgB,EAAc,CAC1B,QAAQ,eACR,YAAY,gBACZ,WACA,aAAa,EAAA,mBACb,wBACA,mBACA,GAAG,GACgB,CACnB,GAAM,CAAE,SAAQ,qBAAoB,WAAY,EAAA,iBAAiB,CAAE,uBAAsB,CAAC,EACpF,CAAC,EAAU,IAAA,EAAe,EAAA,SAAA,CAAS,EAAK,EACxC,GAAA,EAAS,EAAA,MAAA,CAAM,EAErB,GAAI,IAAW,OAAQ,OAAO,KAE9B,GAAI,IAAW,SACX,OACI,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CACI,QAAS,SAAY,CACjB,IAAM,EAAW,MAAM,EAAQ,EAC/B,IAAW,EAAW,WAAa,WAAW,CAClD,EACA,GAAI,EAEH,SAAA,CACG,CAAA,EAIhB,IAAM,EAAO,EAAW,CAAE,SAAQ,oBAAmB,CAAC,EAEtD,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,GAAG,EAAA,QAAO,QAAS,CAAgB,EAAnD,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CACI,gBAAe,EACf,gBAAe,GAAY,EAAO,EAAS,IAAA,GAC3C,YAAe,EAAa,GAAS,CAAC,CAAI,EAC1C,GAAI,EAEH,SAAA,CACG,CAAA,EACP,GAAY,GACT,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAW,EAAA,QAAO,KAAM,GAAI,EAC1B,SAAA,CACF,CAAA,EACH,IACH,GAEb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstallButton.js","names":[],"sources":["../../../src/components/InstallButton/InstallButton.tsx"],"sourcesContent":["import { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Button, type
|
|
1
|
+
{"version":3,"file":"InstallButton.js","names":[],"sources":["../../../src/components/InstallButton/InstallButton.tsx"],"sourcesContent":["import { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Button, type ButtonAsButtonProps } from \"@/components/Button\";\nimport { useInstallPrompt } from \"@/hooks/use-install-prompt\";\nimport { cn } from \"@/utils/cn\";\nimport { defaultInstallHint, type RenderInstallHint } from \"./install-hints\";\nimport styles from \"./InstallButton.module.css\";\n\nexport type InstallOutcome = \"accepted\" | \"dismissed\" | \"unsupported\";\n\nexport interface InstallButtonProps extends Omit<ButtonAsButtonProps, \"onClick\" | \"children\"> {\n /** Button label. Default `\"Instalar app\"`. */\n label?: ReactNode;\n /**\n * Label used when the browser cannot be prompted and the button reveals the\n * manual instruction instead. Default `\"Como instalar\"`.\n */\n hintLabel?: ReactNode;\n /** Called with the user's choice after the install prompt resolves. */\n onResult?: (outcome: InstallOutcome) => void;\n /**\n * Replaces the instruction shown for the `\"ios\"` and `\"manual\"` methods.\n *\n * The default copy is in PT-BR and names the real menu entries. Pass this to\n * translate it, to shorten it, or to point at a screenshot of your own.\n */\n renderHint?: RenderInstallHint;\n /**\n * How long, in ms, to wait for `beforeinstallprompt` before falling back to\n * the manual instruction. Forwarded to {@link useInstallPrompt}; defaults to\n * 3000 there.\n */\n manualFallbackDelayMs?: number;\n /** Class applied to the wrapper that holds the button and the instruction. */\n wrapperClassName?: string;\n}\n\n/**\n * Button wired to PWA installation, through {@link useInstallPrompt}.\n *\n * Where the browser fires `beforeinstallprompt`, the click installs. Where it\n * does not — iOS Safari, and the Android Chromium forks (Mi Browser, UC, Opera\n * Mini, Huawei) that strip the API — the click reveals the instruction for that\n * platform instead of the button disappearing.\n *\n * That disappearance was the defect: the component was built on\n * `useBeforeInstallPrompt`, so it rendered `null` exactly where the user needs\n * the most help, and every app re-implemented the iOS and manual paths locally.\n * Nothing renders only when there is genuinely nothing to offer — already\n * installed, running standalone, or inside the decline cooldown.\n *\n * Inherits every {@link Button} prop of the `<button>` mode (`variant`, `size`,\n * `leftIcon`, …) but not `href`: its click opens the install prompt\n * or toggles the instruction, which is an action, not a navigation.\n *\n * @example\n * <InstallButton variant=\"primary\" leftIcon={<Download />} />\n *\n * @example\n * <InstallButton renderHint={({ method }) => (method === \"ios\" ? <IOSSteps /> : <MenuSteps />)} />\n */\nexport function InstallButton({\n label = \"Instalar app\",\n hintLabel = \"Como instalar\",\n onResult,\n renderHint = defaultInstallHint,\n manualFallbackDelayMs,\n wrapperClassName,\n ...props\n}: InstallButtonProps) {\n const { method, openInChromeIntent, install } = useInstallPrompt({ manualFallbackDelayMs });\n const [hintOpen, setHintOpen] = useState(false);\n const hintId = useId();\n\n if (method === \"none\") return null;\n\n if (method === \"native\") {\n return (\n <Button\n onClick={async () => {\n const accepted = await install();\n onResult?.(accepted ? \"accepted\" : \"dismissed\");\n }}\n {...props}\n >\n {label}\n </Button>\n );\n }\n\n const hint = renderHint({ method, openInChromeIntent });\n\n return (\n <div className={cn(styles.wrapper, wrapperClassName)}>\n <Button\n aria-expanded={hintOpen}\n aria-controls={hintOpen && hint ? hintId : undefined}\n onClick={() => setHintOpen((open) => !open)}\n {...props}\n >\n {hintLabel}\n </Button>\n {hintOpen && hint ? (\n <p className={styles.hint} id={hintId}>\n {hint}\n </p>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;;;;;;AA6DA,SAAgB,EAAc,EAC1B,WAAQ,gBACR,eAAY,iBACZ,aACA,gBAAa,GACb,0BACA,qBACA,GAAG,KACgB;CACnB,IAAM,EAAE,WAAQ,uBAAoB,eAAY,EAAiB,EAAE,yBAAsB,CAAC,GACpF,CAAC,GAAU,KAAe,EAAS,EAAK,GACxC,IAAS,EAAM;CAErB,IAAI,MAAW,QAAQ,OAAO;CAE9B,IAAI,MAAW,UACX,OACI,kBAAC,GAAD;EACI,SAAS,YAAY;GACjB,IAAM,IAAW,MAAM,EAAQ;GAC/B,IAAW,IAAW,aAAa,WAAW;EAClD;EACA,GAAI;EAEH,UAAA;CACG,CAAA;CAIhB,IAAM,IAAO,EAAW;EAAE;EAAQ;CAAmB,CAAC;CAEtD,OACI,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,SAAS,CAAgB;EAAnD,UAAA,CACI,kBAAC,GAAD;GACI,iBAAe;GACf,iBAAe,KAAY,IAAO,IAAS,KAAA;GAC3C,eAAe,GAAa,MAAS,CAAC,CAAI;GAC1C,GAAI;GAEH,UAAA;EACG,CAAA,GACP,KAAY,IACT,kBAAC,KAAD;GAAG,WAAW,EAAO;GAAM,IAAI;GAC1B,UAAA;EACF,CAAA,IACH,IACH;;AAEb"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../../utils/cn.cjs"),t=require("../Portal/escape-layer.cjs"),n=require("../../hooks/use-focus-trap.cjs"),r=require("../Portal/portal-host.cjs"),i=require("./Modal.module.cjs");let a=require("react"),o=require("react/jsx-runtime"),s=require("react-dom");function c({open:c,onClose:d,title:f,children:p,footer:m,size:h=`md`,closeOnBackdrop:g=!0,closeOnEsc:_=!0,className:v,hideCloseButton:y=!1,fullscreen:b=!1,fullscreenOnMobile:x=!1,"aria-label":S}){let C=(0,a.useId)(),w=(0,a.useRef)(null);n.useFocusTrap(w,c),t.useEscapeLayer(c,_?d:null),(0,a.useEffect)(()=>{if(!c)return;let e=document.body.style.overflow;return document.body.style.overflow=`hidden`,()=>{document.body.style.overflow=e}},[c]);let T=r.usePortalHost();return!c||!T?null:(0,s.createPortal)((0,o.jsx)(`div`,{className:i.default.overlay,role:`presentation`,onClick:()=>{g&&d()},children:(0,o.jsxs)(`div`,{ref:w,role:`dialog`,"aria-modal":`true`,tabIndex:-1,"aria-labelledby":f?C:void 0,"aria-label":f?void 0:S,className:e.cn(i.default.dialog,l(h),b&&i.default.fullscreen,x&&i.default.fullscreenOnMobile,v),onClick:e=>e.stopPropagation(),children:[(f||!y)&&(0,o.jsxs)(`header`,{className:i.default.header,children:[f&&(0,o.jsx)(`h3`,{id:C,className:i.default.title,children:f}),!y&&(0,o.jsx)(`button`,{type:`button`,className:i.default.close,"aria-label":`Fechar`,onClick:d,children:(0,o.jsx)(u,{})})]}),(0,o.jsx)(`div`,{className:i.default.body,children:p}),m&&(0,o.jsx)(`footer`,{className:i.default.footer,children:m})]})}),T)}function l(e){return e===`2xl`?i.default.
|
|
1
|
+
const e=require("../../utils/cn.cjs"),t=require("../Portal/escape-layer.cjs"),n=require("../../hooks/use-focus-trap.cjs"),r=require("../Portal/portal-host.cjs"),i=require("./Modal.module.cjs");let a=require("react"),o=require("react/jsx-runtime"),s=require("react-dom");function c({open:c,onClose:d,title:f,children:p,footer:m,size:h=`md`,closeOnBackdrop:g=!0,closeOnEsc:_=!0,className:v,hideCloseButton:y=!1,fullscreen:b=!1,fullscreenOnMobile:x=!1,"aria-label":S}){let C=(0,a.useId)(),w=(0,a.useRef)(null);n.useFocusTrap(w,c),t.useEscapeLayer(c,_?d:null),(0,a.useEffect)(()=>{if(!c)return;let e=document.body.style.overflow;return document.body.style.overflow=`hidden`,()=>{document.body.style.overflow=e}},[c]);let T=r.usePortalHost();return!c||!T?null:(0,s.createPortal)((0,o.jsx)(`div`,{className:i.default.overlay,role:`presentation`,onClick:()=>{g&&d()},children:(0,o.jsxs)(`div`,{ref:w,role:`dialog`,"aria-modal":`true`,tabIndex:-1,"aria-labelledby":f?C:void 0,"aria-label":f?void 0:S,className:e.cn(i.default.dialog,l(h),b&&i.default.fullscreen,x&&i.default.fullscreenOnMobile,v),onClick:e=>e.stopPropagation(),children:[(f||!y)&&(0,o.jsxs)(`header`,{className:i.default.header,children:[f&&(0,o.jsx)(`h3`,{id:C,className:i.default.title,children:f}),!y&&(0,o.jsx)(`button`,{type:`button`,className:i.default.close,"aria-label":`Fechar`,onClick:d,children:(0,o.jsx)(u,{})})]}),(0,o.jsx)(`div`,{className:i.default.body,children:p}),m&&(0,o.jsx)(`footer`,{className:i.default.footer,children:m})]})}),T)}function l(e){return e===`2xl`?i.default.size2Xl:e===`3xl`?i.default.size3Xl:i.default[e]}function u(){return(0,o.jsx)(`svg`,{width:`18`,height:`18`,viewBox:`0 0 24 24`,fill:`none`,children:(0,o.jsx)(`path`,{d:`M6 6l12 12M6 18L18 6`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`})})}exports.Modal=c;
|
|
2
2
|
//# sourceMappingURL=Modal.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.cjs","names":[],"sources":["../../../src/components/Modal/Modal.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count, function-lines — size, fullscreen and\n * fullscreenOnMobile are three distinct decisions (a fixed width, always full, full\n * only on a phone), and the rest is the dialog contract: open, onClose, title,\n * children, footer, closeOnBackdrop, closeOnEsc, hideCloseButton. The body is the\n * focus trap and the scroll lock, which must be installed and torn down together.\n */\nimport { useEffect, useId, useRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useEscapeLayer } from \"@/components/Portal/escape-layer\";\nimport { useFocusTrap } from \"@/hooks/use-focus-trap\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Modal.module.css\";\nimport { usePortalHost } from \"../Portal/portal-host\";\n\nexport type ModalSize = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\" | \"3xl\";\n\nexport interface ModalProps {\n open: boolean;\n onClose: () => void;\n title?: ReactNode;\n children?: ReactNode;\n footer?: ReactNode;\n size?: ModalSize;\n closeOnBackdrop?: boolean;\n closeOnEsc?: boolean;\n className?: string;\n hideCloseButton?: boolean;\n /** Force fullscreen at all breakpoints. */\n fullscreen?: boolean;\n /** Auto-fullscreen on mobile viewports (< 640px). Default `false`. */\n fullscreenOnMobile?: boolean;\n /**\n * Accessible name for the dialog. Only needed when there is no `title` —\n * with a `title` the dialog is named by it through `aria-labelledby`.\n */\n \"aria-label\"?: string;\n}\n\n/**\n * Portal-rendered modal dialog with backdrop, Esc handler, and slots for\n * header/body/footer. Locks body scroll while open.\n *\n * Keyboard focus is trapped in the dialog while it is open (`useFocusTrap`): it\n * enters on the first tab stop — or the dialog itself when there is none —,\n * `Tab`/`Shift+Tab` cycle inside it, including the panels of a `Popover` or\n * `HoverCard` opened from it, and closing returns focus to the element that\n * opened it. `aria-modal=\"true\"` tells a screen reader the page behind is inert;\n * the trap is what makes that true for the keyboard.\n *\n * The `dialog` role needs an accessible name: a `title` supplies it via\n * `aria-labelledby`, and a titleless dialog should pass `aria-label`. The\n * header heading is only rendered when there is a title, so a close-button-only\n * header does not leave an empty `h3` behind.\n */\nexport function Modal({\n open,\n onClose,\n title,\n children,\n footer,\n size = \"md\",\n closeOnBackdrop = true,\n closeOnEsc = true,\n className,\n hideCloseButton = false,\n fullscreen = false,\n fullscreenOnMobile = false,\n \"aria-label\": ariaLabel,\n}: ModalProps) {\n const titleId = useId();\n const dialogRef = useRef<HTMLDivElement>(null);\n useFocusTrap(dialogRef, open);\n useEscapeLayer(open, closeOnEsc ? onClose : null);\n useEffect(() => {\n if (!open) return;\n const previousOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = previousOverflow;\n };\n }, [open]);\n\n const portalHost = usePortalHost();\n\n if (!open || !portalHost) return null;\n\n return createPortal(\n <div\n className={styles.overlay}\n role=\"presentation\"\n onClick={() => {\n if (closeOnBackdrop) onClose();\n }}\n >\n <div\n ref={dialogRef}\n role=\"dialog\"\n aria-modal=\"true\"\n tabIndex={-1}\n aria-labelledby={title ? titleId : undefined}\n aria-label={title ? undefined : ariaLabel}\n className={cn(\n styles.dialog,\n sizeClassName(size),\n fullscreen && styles.fullscreen,\n fullscreenOnMobile && styles.fullscreenOnMobile,\n className,\n )}\n onClick={(event) => event.stopPropagation()}\n >\n {(title || !hideCloseButton) && (\n <header className={styles.header}>\n {title && (\n <h3 id={titleId} className={styles.title}>\n {title}\n </h3>\n )}\n {!hideCloseButton && (\n <button\n type=\"button\"\n className={styles.close}\n aria-label=\"Fechar\"\n onClick={onClose}\n >\n <CloseIcon />\n </button>\n )}\n </header>\n )}\n <div className={styles.body}>{children}</div>\n {footer && <footer className={styles.footer}>{footer}</footer>}\n </div>\n </div>,\n portalHost,\n );\n}\n\nfunction sizeClassName(size: ModalSize): string | undefined {\n if (size === \"2xl\") return styles.
|
|
1
|
+
{"version":3,"file":"Modal.cjs","names":[],"sources":["../../../src/components/Modal/Modal.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count, function-lines — size, fullscreen and\n * fullscreenOnMobile are three distinct decisions (a fixed width, always full, full\n * only on a phone), and the rest is the dialog contract: open, onClose, title,\n * children, footer, closeOnBackdrop, closeOnEsc, hideCloseButton. The body is the\n * focus trap and the scroll lock, which must be installed and torn down together.\n */\nimport { useEffect, useId, useRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useEscapeLayer } from \"@/components/Portal/escape-layer\";\nimport { useFocusTrap } from \"@/hooks/use-focus-trap\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Modal.module.css\";\nimport { usePortalHost } from \"../Portal/portal-host\";\n\nexport type ModalSize = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\" | \"3xl\";\n\nexport interface ModalProps {\n open: boolean;\n onClose: () => void;\n title?: ReactNode;\n children?: ReactNode;\n footer?: ReactNode;\n size?: ModalSize;\n closeOnBackdrop?: boolean;\n closeOnEsc?: boolean;\n className?: string;\n hideCloseButton?: boolean;\n /** Force fullscreen at all breakpoints. */\n fullscreen?: boolean;\n /** Auto-fullscreen on mobile viewports (< 640px). Default `false`. */\n fullscreenOnMobile?: boolean;\n /**\n * Accessible name for the dialog. Only needed when there is no `title` —\n * with a `title` the dialog is named by it through `aria-labelledby`.\n */\n \"aria-label\"?: string;\n}\n\n/**\n * Portal-rendered modal dialog with backdrop, Esc handler, and slots for\n * header/body/footer. Locks body scroll while open.\n *\n * Keyboard focus is trapped in the dialog while it is open (`useFocusTrap`): it\n * enters on the first tab stop — or the dialog itself when there is none —,\n * `Tab`/`Shift+Tab` cycle inside it, including the panels of a `Popover` or\n * `HoverCard` opened from it, and closing returns focus to the element that\n * opened it. `aria-modal=\"true\"` tells a screen reader the page behind is inert;\n * the trap is what makes that true for the keyboard.\n *\n * The `dialog` role needs an accessible name: a `title` supplies it via\n * `aria-labelledby`, and a titleless dialog should pass `aria-label`. The\n * header heading is only rendered when there is a title, so a close-button-only\n * header does not leave an empty `h3` behind.\n */\nexport function Modal({\n open,\n onClose,\n title,\n children,\n footer,\n size = \"md\",\n closeOnBackdrop = true,\n closeOnEsc = true,\n className,\n hideCloseButton = false,\n fullscreen = false,\n fullscreenOnMobile = false,\n \"aria-label\": ariaLabel,\n}: ModalProps) {\n const titleId = useId();\n const dialogRef = useRef<HTMLDivElement>(null);\n useFocusTrap(dialogRef, open);\n useEscapeLayer(open, closeOnEsc ? onClose : null);\n useEffect(() => {\n if (!open) return;\n const previousOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = previousOverflow;\n };\n }, [open]);\n\n const portalHost = usePortalHost();\n\n if (!open || !portalHost) return null;\n\n return createPortal(\n <div\n className={styles.overlay}\n role=\"presentation\"\n onClick={() => {\n if (closeOnBackdrop) onClose();\n }}\n >\n <div\n ref={dialogRef}\n role=\"dialog\"\n aria-modal=\"true\"\n tabIndex={-1}\n aria-labelledby={title ? titleId : undefined}\n aria-label={title ? undefined : ariaLabel}\n className={cn(\n styles.dialog,\n sizeClassName(size),\n fullscreen && styles.fullscreen,\n fullscreenOnMobile && styles.fullscreenOnMobile,\n className,\n )}\n onClick={(event) => event.stopPropagation()}\n >\n {(title || !hideCloseButton) && (\n <header className={styles.header}>\n {title && (\n <h3 id={titleId} className={styles.title}>\n {title}\n </h3>\n )}\n {!hideCloseButton && (\n <button\n type=\"button\"\n className={styles.close}\n aria-label=\"Fechar\"\n onClick={onClose}\n >\n <CloseIcon />\n </button>\n )}\n </header>\n )}\n <div className={styles.body}>{children}</div>\n {footer && <footer className={styles.footer}>{footer}</footer>}\n </div>\n </div>,\n portalHost,\n );\n}\n\n/**\n * Resolve the width class for a {@link ModalSize}.\n *\n * `2xl`/`3xl` are not valid CSS identifiers, so their rules are `.size2Xl` and\n * `.size3Xl` — spelled exactly as the build exports them. The build camelCases\n * CSS-module keys (`localsConvention: \"camelCaseOnly\"`), which turns `.size2xl`\n * into the key `size2Xl`; a lookup of `styles.size2xl` was `undefined` in `dist/`\n * and both sizes rendered with no `max-width` at all (issue #405).\n *\n * @param size - The requested modal size.\n * @returns The CSS-module class name for that size.\n */\nfunction sizeClassName(size: ModalSize): string | undefined {\n if (size === \"2xl\") return styles.size2Xl;\n if (size === \"3xl\") return styles.size3Xl;\n return styles[size];\n}\n\nfunction CloseIcon() {\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\">\n <path\n d=\"M6 6l12 12M6 18L18 6\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n"],"mappings":"8QAwDA,SAAgB,EAAM,CAClB,OACA,UACA,QACA,WACA,SACA,OAAO,KACP,kBAAkB,GAClB,aAAa,GACb,YACA,kBAAkB,GAClB,aAAa,GACb,qBAAqB,GACrB,aAAc,GACH,CACX,IAAM,GAAA,EAAU,EAAA,MAAA,CAAM,EAChB,GAAA,EAAY,EAAA,OAAA,CAAuB,IAAI,EAC7C,EAAA,aAAa,EAAW,CAAI,EAC5B,EAAA,eAAe,EAAM,EAAa,EAAU,IAAI,GAChD,EAAA,EAAA,UAAA,KAAgB,CACZ,GAAI,CAAC,EAAM,OACX,IAAM,EAAmB,SAAS,KAAK,MAAM,SAE7C,MADA,UAAS,KAAK,MAAM,SAAW,aAClB,CACT,SAAS,KAAK,MAAM,SAAW,CACnC,CACJ,EAAG,CAAC,CAAI,CAAC,EAET,IAAM,EAAa,EAAA,cAAc,EAIjC,MAFI,CAAC,GAAQ,CAAC,EAAmB,MAEjC,EAAO,EAAA,aAAA,EACH,EAAA,EAAA,IAAA,CAAC,MAAD,CACI,UAAW,EAAA,QAAO,QAClB,KAAK,eACL,YAAe,CACP,GAAiB,EAAQ,CACjC,EAEA,UAAA,EAAA,EAAA,KAAA,CAAC,MAAD,CACI,IAAK,EACL,KAAK,SACL,aAAW,OACX,SAAU,GACV,kBAAiB,EAAQ,EAAU,IAAA,GACnC,aAAY,EAAQ,IAAA,GAAY,EAChC,UAAW,EAAA,GACP,EAAA,QAAO,OACP,EAAc,CAAI,EAClB,GAAc,EAAA,QAAO,WACrB,GAAsB,EAAA,QAAO,mBAC7B,CACJ,EACA,QAAU,GAAU,EAAM,gBAAgB,EAd9C,SAAA,EAgBM,GAAS,CAAC,KACR,EAAA,EAAA,KAAA,CAAC,SAAD,CAAQ,UAAW,EAAA,QAAO,OAA1B,SAAA,CACK,IACG,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,GAAI,EAAS,UAAW,EAAA,QAAO,MAC9B,SAAA,CACD,CAAA,EAEP,CAAC,IACE,EAAA,EAAA,IAAA,CAAC,SAAD,CACI,KAAK,SACL,UAAW,EAAA,QAAO,MAClB,aAAW,SACX,QAAS,EAET,UAAA,EAAA,EAAA,IAAA,CAAC,EAAD,CAAY,CAAA,CACR,CAAA,CAER,KAEZ,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,KAAO,UAAc,CAAA,EAC3C,IAAU,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,UAAW,EAAA,QAAO,OAAS,SAAA,CAAe,CAAA,CAC5D,GACJ,CAAA,EACL,CACJ,CACJ,CAcA,SAAS,EAAc,EAAqC,CAGxD,OAFI,IAAS,MAAc,EAAA,QAAO,QAC9B,IAAS,MAAc,EAAA,QAAO,QAC3B,EAAA,QAAO,EAClB,CAEA,SAAS,GAAY,CACjB,OACI,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OACjD,UAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CACI,EAAE,uBACF,OAAO,eACP,YAAY,IACZ,cAAc,OACjB,CAAA,CACA,CAAA,CAEb"}
|
|
@@ -60,7 +60,7 @@ function d({ open: d, onClose: m, title: h, children: g, footer: _, size: v = "m
|
|
|
60
60
|
}), O);
|
|
61
61
|
}
|
|
62
62
|
function f(e) {
|
|
63
|
-
return e === "2xl" ? i.
|
|
63
|
+
return e === "2xl" ? i.size2Xl : e === "3xl" ? i.size3Xl : i[e];
|
|
64
64
|
}
|
|
65
65
|
function p() {
|
|
66
66
|
return /* @__PURE__ */ c("svg", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.js","names":[],"sources":["../../../src/components/Modal/Modal.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count, function-lines — size, fullscreen and\n * fullscreenOnMobile are three distinct decisions (a fixed width, always full, full\n * only on a phone), and the rest is the dialog contract: open, onClose, title,\n * children, footer, closeOnBackdrop, closeOnEsc, hideCloseButton. The body is the\n * focus trap and the scroll lock, which must be installed and torn down together.\n */\nimport { useEffect, useId, useRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useEscapeLayer } from \"@/components/Portal/escape-layer\";\nimport { useFocusTrap } from \"@/hooks/use-focus-trap\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Modal.module.css\";\nimport { usePortalHost } from \"../Portal/portal-host\";\n\nexport type ModalSize = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\" | \"3xl\";\n\nexport interface ModalProps {\n open: boolean;\n onClose: () => void;\n title?: ReactNode;\n children?: ReactNode;\n footer?: ReactNode;\n size?: ModalSize;\n closeOnBackdrop?: boolean;\n closeOnEsc?: boolean;\n className?: string;\n hideCloseButton?: boolean;\n /** Force fullscreen at all breakpoints. */\n fullscreen?: boolean;\n /** Auto-fullscreen on mobile viewports (< 640px). Default `false`. */\n fullscreenOnMobile?: boolean;\n /**\n * Accessible name for the dialog. Only needed when there is no `title` —\n * with a `title` the dialog is named by it through `aria-labelledby`.\n */\n \"aria-label\"?: string;\n}\n\n/**\n * Portal-rendered modal dialog with backdrop, Esc handler, and slots for\n * header/body/footer. Locks body scroll while open.\n *\n * Keyboard focus is trapped in the dialog while it is open (`useFocusTrap`): it\n * enters on the first tab stop — or the dialog itself when there is none —,\n * `Tab`/`Shift+Tab` cycle inside it, including the panels of a `Popover` or\n * `HoverCard` opened from it, and closing returns focus to the element that\n * opened it. `aria-modal=\"true\"` tells a screen reader the page behind is inert;\n * the trap is what makes that true for the keyboard.\n *\n * The `dialog` role needs an accessible name: a `title` supplies it via\n * `aria-labelledby`, and a titleless dialog should pass `aria-label`. The\n * header heading is only rendered when there is a title, so a close-button-only\n * header does not leave an empty `h3` behind.\n */\nexport function Modal({\n open,\n onClose,\n title,\n children,\n footer,\n size = \"md\",\n closeOnBackdrop = true,\n closeOnEsc = true,\n className,\n hideCloseButton = false,\n fullscreen = false,\n fullscreenOnMobile = false,\n \"aria-label\": ariaLabel,\n}: ModalProps) {\n const titleId = useId();\n const dialogRef = useRef<HTMLDivElement>(null);\n useFocusTrap(dialogRef, open);\n useEscapeLayer(open, closeOnEsc ? onClose : null);\n useEffect(() => {\n if (!open) return;\n const previousOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = previousOverflow;\n };\n }, [open]);\n\n const portalHost = usePortalHost();\n\n if (!open || !portalHost) return null;\n\n return createPortal(\n <div\n className={styles.overlay}\n role=\"presentation\"\n onClick={() => {\n if (closeOnBackdrop) onClose();\n }}\n >\n <div\n ref={dialogRef}\n role=\"dialog\"\n aria-modal=\"true\"\n tabIndex={-1}\n aria-labelledby={title ? titleId : undefined}\n aria-label={title ? undefined : ariaLabel}\n className={cn(\n styles.dialog,\n sizeClassName(size),\n fullscreen && styles.fullscreen,\n fullscreenOnMobile && styles.fullscreenOnMobile,\n className,\n )}\n onClick={(event) => event.stopPropagation()}\n >\n {(title || !hideCloseButton) && (\n <header className={styles.header}>\n {title && (\n <h3 id={titleId} className={styles.title}>\n {title}\n </h3>\n )}\n {!hideCloseButton && (\n <button\n type=\"button\"\n className={styles.close}\n aria-label=\"Fechar\"\n onClick={onClose}\n >\n <CloseIcon />\n </button>\n )}\n </header>\n )}\n <div className={styles.body}>{children}</div>\n {footer && <footer className={styles.footer}>{footer}</footer>}\n </div>\n </div>,\n portalHost,\n );\n}\n\nfunction sizeClassName(size: ModalSize): string | undefined {\n if (size === \"2xl\") return styles.
|
|
1
|
+
{"version":3,"file":"Modal.js","names":[],"sources":["../../../src/components/Modal/Modal.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count, function-lines — size, fullscreen and\n * fullscreenOnMobile are three distinct decisions (a fixed width, always full, full\n * only on a phone), and the rest is the dialog contract: open, onClose, title,\n * children, footer, closeOnBackdrop, closeOnEsc, hideCloseButton. The body is the\n * focus trap and the scroll lock, which must be installed and torn down together.\n */\nimport { useEffect, useId, useRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useEscapeLayer } from \"@/components/Portal/escape-layer\";\nimport { useFocusTrap } from \"@/hooks/use-focus-trap\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Modal.module.css\";\nimport { usePortalHost } from \"../Portal/portal-host\";\n\nexport type ModalSize = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\" | \"3xl\";\n\nexport interface ModalProps {\n open: boolean;\n onClose: () => void;\n title?: ReactNode;\n children?: ReactNode;\n footer?: ReactNode;\n size?: ModalSize;\n closeOnBackdrop?: boolean;\n closeOnEsc?: boolean;\n className?: string;\n hideCloseButton?: boolean;\n /** Force fullscreen at all breakpoints. */\n fullscreen?: boolean;\n /** Auto-fullscreen on mobile viewports (< 640px). Default `false`. */\n fullscreenOnMobile?: boolean;\n /**\n * Accessible name for the dialog. Only needed when there is no `title` —\n * with a `title` the dialog is named by it through `aria-labelledby`.\n */\n \"aria-label\"?: string;\n}\n\n/**\n * Portal-rendered modal dialog with backdrop, Esc handler, and slots for\n * header/body/footer. Locks body scroll while open.\n *\n * Keyboard focus is trapped in the dialog while it is open (`useFocusTrap`): it\n * enters on the first tab stop — or the dialog itself when there is none —,\n * `Tab`/`Shift+Tab` cycle inside it, including the panels of a `Popover` or\n * `HoverCard` opened from it, and closing returns focus to the element that\n * opened it. `aria-modal=\"true\"` tells a screen reader the page behind is inert;\n * the trap is what makes that true for the keyboard.\n *\n * The `dialog` role needs an accessible name: a `title` supplies it via\n * `aria-labelledby`, and a titleless dialog should pass `aria-label`. The\n * header heading is only rendered when there is a title, so a close-button-only\n * header does not leave an empty `h3` behind.\n */\nexport function Modal({\n open,\n onClose,\n title,\n children,\n footer,\n size = \"md\",\n closeOnBackdrop = true,\n closeOnEsc = true,\n className,\n hideCloseButton = false,\n fullscreen = false,\n fullscreenOnMobile = false,\n \"aria-label\": ariaLabel,\n}: ModalProps) {\n const titleId = useId();\n const dialogRef = useRef<HTMLDivElement>(null);\n useFocusTrap(dialogRef, open);\n useEscapeLayer(open, closeOnEsc ? onClose : null);\n useEffect(() => {\n if (!open) return;\n const previousOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = previousOverflow;\n };\n }, [open]);\n\n const portalHost = usePortalHost();\n\n if (!open || !portalHost) return null;\n\n return createPortal(\n <div\n className={styles.overlay}\n role=\"presentation\"\n onClick={() => {\n if (closeOnBackdrop) onClose();\n }}\n >\n <div\n ref={dialogRef}\n role=\"dialog\"\n aria-modal=\"true\"\n tabIndex={-1}\n aria-labelledby={title ? titleId : undefined}\n aria-label={title ? undefined : ariaLabel}\n className={cn(\n styles.dialog,\n sizeClassName(size),\n fullscreen && styles.fullscreen,\n fullscreenOnMobile && styles.fullscreenOnMobile,\n className,\n )}\n onClick={(event) => event.stopPropagation()}\n >\n {(title || !hideCloseButton) && (\n <header className={styles.header}>\n {title && (\n <h3 id={titleId} className={styles.title}>\n {title}\n </h3>\n )}\n {!hideCloseButton && (\n <button\n type=\"button\"\n className={styles.close}\n aria-label=\"Fechar\"\n onClick={onClose}\n >\n <CloseIcon />\n </button>\n )}\n </header>\n )}\n <div className={styles.body}>{children}</div>\n {footer && <footer className={styles.footer}>{footer}</footer>}\n </div>\n </div>,\n portalHost,\n );\n}\n\n/**\n * Resolve the width class for a {@link ModalSize}.\n *\n * `2xl`/`3xl` are not valid CSS identifiers, so their rules are `.size2Xl` and\n * `.size3Xl` — spelled exactly as the build exports them. The build camelCases\n * CSS-module keys (`localsConvention: \"camelCaseOnly\"`), which turns `.size2xl`\n * into the key `size2Xl`; a lookup of `styles.size2xl` was `undefined` in `dist/`\n * and both sizes rendered with no `max-width` at all (issue #405).\n *\n * @param size - The requested modal size.\n * @returns The CSS-module class name for that size.\n */\nfunction sizeClassName(size: ModalSize): string | undefined {\n if (size === \"2xl\") return styles.size2Xl;\n if (size === \"3xl\") return styles.size3Xl;\n return styles[size];\n}\n\nfunction CloseIcon() {\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\">\n <path\n d=\"M6 6l12 12M6 18L18 6\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n"],"mappings":";;;;;;;;;AAwDA,SAAgB,EAAM,EAClB,SACA,YACA,UACA,aACA,WACA,UAAO,MACP,qBAAkB,IAClB,gBAAa,IACb,cACA,qBAAkB,IAClB,gBAAa,IACb,wBAAqB,IACrB,cAAc,KACH;CACX,IAAM,IAAU,EAAM,GAChB,IAAY,EAAuB,IAAI;CAG7C,AAFA,EAAa,GAAW,CAAI,GAC5B,EAAe,GAAM,IAAa,IAAU,IAAI,GAChD,QAAgB;EACZ,IAAI,CAAC,GAAM;EACX,IAAM,IAAmB,SAAS,KAAK,MAAM;EAE7C,OADA,SAAS,KAAK,MAAM,WAAW,gBAClB;GACT,SAAS,KAAK,MAAM,WAAW;EACnC;CACJ,GAAG,CAAC,CAAI,CAAC;CAET,IAAM,IAAa,EAAc;CAIjC,OAFI,CAAC,KAAQ,CAAC,IAAmB,OAE1B,EACH,kBAAC,OAAD;EACI,WAAW,EAAO;EAClB,MAAK;EACL,eAAe;GACX,AAAI,KAAiB,EAAQ;EACjC;EAEA,UAAA,kBAAC,OAAD;GACI,KAAK;GACL,MAAK;GACL,cAAW;GACX,UAAU;GACV,mBAAiB,IAAQ,IAAU,KAAA;GACnC,cAAY,IAAQ,KAAA,IAAY;GAChC,WAAW,EACP,EAAO,QACP,EAAc,CAAI,GAClB,KAAc,EAAO,YACrB,KAAsB,EAAO,oBAC7B,CACJ;GACA,UAAU,MAAU,EAAM,gBAAgB;GAd9C,UAAA;KAgBM,KAAS,CAAC,MACR,kBAAC,UAAD;KAAQ,WAAW,EAAO;KAA1B,UAAA,CACK,KACG,kBAAC,MAAD;MAAI,IAAI;MAAS,WAAW,EAAO;MAC9B,UAAA;KACD,CAAA,GAEP,CAAC,KACE,kBAAC,UAAD;MACI,MAAK;MACL,WAAW,EAAO;MAClB,cAAW;MACX,SAAS;MAET,UAAA,kBAAC,GAAD,CAAY,CAAA;KACR,CAAA,CAER;;IAEZ,kBAAC,OAAD;KAAK,WAAW,EAAO;KAAO;IAAc,CAAA;IAC3C,KAAU,kBAAC,UAAD;KAAQ,WAAW,EAAO;KAAS,UAAA;IAAe,CAAA;GAC5D;;CACJ,CAAA,GACL,CACJ;AACJ;AAcA,SAAS,EAAc,GAAqC;CAGxD,OAFI,MAAS,QAAc,EAAO,UAC9B,MAAS,QAAc,EAAO,UAC3B,EAAO;AAClB;AAEA,SAAS,IAAY;CACjB,OACI,kBAAC,OAAD;EAAK,OAAM;EAAK,QAAO;EAAK,SAAQ;EAAY,MAAK;EACjD,UAAA,kBAAC,QAAD;GACI,GAAE;GACF,QAAO;GACP,aAAY;GACZ,eAAc;EACjB,CAAA;CACA,CAAA;AAEb"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
require("../../styles/component/Modal.css");
|
|
2
|
-
var e=`tempest_overlay_dd9h1`,t=`tempest_tempest-fade-in_DvgSp`,n=`tempest_dialog_ptM-K`,r=`tempest_tempest-modal-in_UoxQC`,i=`tempest_sm_K5k3W`,a=`tempest_md_gvyR7`,o=`tempest_lg_BgB1a`,s=`tempest_xl_MR-68`,c=`
|
|
2
|
+
var e=`tempest_overlay_dd9h1`,t=`tempest_tempest-fade-in_DvgSp`,n=`tempest_dialog_ptM-K`,r=`tempest_tempest-modal-in_UoxQC`,i=`tempest_sm_K5k3W`,a=`tempest_md_gvyR7`,o=`tempest_lg_BgB1a`,s=`tempest_xl_MR-68`,c=`tempest_size2Xl_oLq5O`,l=`tempest_size3Xl_YzlSH`,u=`tempest_fullscreen_o84Xi`,d=`tempest_fullscreenOnMobile_0bDwe`,f=`tempest_body_lVhql`,p=`tempest_header_ILG9i`,m=`tempest_footer_rro2w`,h=`tempest_title_A5OeE`,g=`tempest_close_-ER1C`,_={overlay:e,tempestFadeIn:t,dialog:n,tempestModalIn:r,sm:i,md:a,lg:o,xl:s,size2Xl:c,size3Xl:l,fullscreen:u,fullscreenOnMobile:d,body:f,header:p,footer:m,title:h,close:g};exports.body=f,exports.close=g,exports.default=_,exports.dialog=n,exports.footer=m,exports.fullscreen=u,exports.fullscreenOnMobile=d,exports.header=p,exports.lg=o,exports.md=a,exports.overlay=e,exports.size2Xl=c,exports.size3Xl=l,exports.sm=i,exports.tempestFadeIn=t,exports.tempestModalIn=r,exports.title=h,exports.xl=s;
|
|
3
3
|
//# sourceMappingURL=Modal.module.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.module.cjs","names":[],"sources":["../../../src/components/Modal/Modal.module.css"],"sourcesContent":[".overlay {\n position: fixed;\n inset: 0;\n background-color: rgba(15, 23, 42, 0.55);\n backdrop-filter: blur(2px);\n -webkit-backdrop-filter: blur(2px);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: max(var(--tempest-space-4), var(--tempest-safe-area-top))\n max(var(--tempest-space-4), var(--tempest-safe-area-right))\n max(var(--tempest-space-4), var(--tempest-safe-area-bottom))\n max(var(--tempest-space-4), var(--tempest-safe-area-left));\n z-index: var(--tempest-z-modal);\n animation: tempest-fade-in var(--tempest-duration-base) var(--tempest-ease-out);\n}\n\n.dialog {\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n border-radius: var(--tempest-radius-xl);\n box-shadow: var(--tempest-shadow-xl);\n width: 100%;\n max-height: 90vh;\n max-height: 90dvh;\n display: flex;\n flex-direction: column;\n animation: tempest-modal-in var(--tempest-duration-base) var(--tempest-ease-emphasized);\n}\n\n.sm {\n max-width: 400px;\n}\n.md {\n max-width: 560px;\n}\n.lg {\n max-width: 800px;\n}\n.xl {\n max-width: 1024px;\n}\n.
|
|
1
|
+
{"version":3,"file":"Modal.module.cjs","names":[],"sources":["../../../src/components/Modal/Modal.module.css"],"sourcesContent":[".overlay {\n position: fixed;\n inset: 0;\n background-color: rgba(15, 23, 42, 0.55);\n backdrop-filter: blur(2px);\n -webkit-backdrop-filter: blur(2px);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: max(var(--tempest-space-4), var(--tempest-safe-area-top))\n max(var(--tempest-space-4), var(--tempest-safe-area-right))\n max(var(--tempest-space-4), var(--tempest-safe-area-bottom))\n max(var(--tempest-space-4), var(--tempest-safe-area-left));\n z-index: var(--tempest-z-modal);\n animation: tempest-fade-in var(--tempest-duration-base) var(--tempest-ease-out);\n}\n\n.dialog {\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n border-radius: var(--tempest-radius-xl);\n box-shadow: var(--tempest-shadow-xl);\n width: 100%;\n max-height: 90vh;\n max-height: 90dvh;\n display: flex;\n flex-direction: column;\n animation: tempest-modal-in var(--tempest-duration-base) var(--tempest-ease-emphasized);\n}\n\n.sm {\n max-width: 400px;\n}\n.md {\n max-width: 560px;\n}\n.lg {\n max-width: 800px;\n}\n.xl {\n max-width: 1024px;\n}\n.size2Xl {\n max-width: 1280px;\n}\n.size3Xl {\n max-width: 1440px;\n}\n\n/* Fullscreen — fill entire viewport regardless of size. */\n.fullscreen {\n max-width: 100%;\n max-height: 100vh;\n max-height: 100dvh;\n width: 100%;\n height: 100%;\n border-radius: 0;\n}\n\n/* Auto-fullscreen below mobile breakpoint. */\n@media (max-width: 639.98px) {\n .fullscreenOnMobile {\n max-width: 100%;\n max-height: 100vh;\n max-height: 100dvh;\n width: 100%;\n height: 100%;\n border-radius: 0;\n }\n}\n\n/* Mobile padding adjustment for non-fullscreen modals. */\n@media (max-width: 639.98px) {\n .dialog:not(.fullscreen):not(.fullscreenOnMobile) {\n border-radius: var(--tempest-radius-lg);\n }\n .body {\n padding: var(--tempest-space-4);\n }\n .header,\n .footer {\n padding: var(--tempest-space-3) var(--tempest-space-4);\n }\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--tempest-space-3);\n padding: var(--tempest-space-4) var(--tempest-space-5);\n border-bottom: 1px solid var(--tempest-border);\n}\n\n.title {\n margin: 0;\n font-size: var(--tempest-text-lg);\n font-weight: var(--tempest-weight-semibold);\n line-height: var(--tempest-leading-snug);\n color: var(--tempest-text);\n}\n\n.close {\n background: none;\n border: none;\n color: var(--tempest-text-muted);\n padding: var(--tempest-space-1);\n border-radius: var(--tempest-radius-sm);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: var(--tempest-transition-color);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .close:hover {\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n }\n}\n\n.close:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n\n.body {\n padding: var(--tempest-space-5);\n overflow-y: auto;\n line-height: var(--tempest-leading-normal);\n}\n\n.footer {\n display: flex;\n justify-content: flex-end;\n gap: var(--tempest-space-2);\n padding: var(--tempest-space-4) var(--tempest-space-5);\n border-top: 1px solid var(--tempest-border);\n background-color: var(--tempest-surface);\n border-radius: 0 0 var(--tempest-radius-xl) var(--tempest-radius-xl);\n}\n\n@keyframes tempest-fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n@keyframes tempest-modal-in {\n from {\n opacity: 0;\n transform: translateY(12px) scale(0.96);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .overlay,\n .dialog {\n animation: none;\n }\n}\n"],"mappings":";"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../../styles/component/Modal.css";
|
|
2
2
|
//#region src/components/Modal/Modal.module.css
|
|
3
|
-
var e = "tempest_overlay_dd9h1", t = "tempest_tempest-fade-in_DvgSp", n = "tempest_dialog_ptM-K", r = "tempest_tempest-modal-in_UoxQC", i = "tempest_sm_K5k3W", a = "tempest_md_gvyR7", o = "tempest_lg_BgB1a", s = "tempest_xl_MR-68", c = "
|
|
3
|
+
var e = "tempest_overlay_dd9h1", t = "tempest_tempest-fade-in_DvgSp", n = "tempest_dialog_ptM-K", r = "tempest_tempest-modal-in_UoxQC", i = "tempest_sm_K5k3W", a = "tempest_md_gvyR7", o = "tempest_lg_BgB1a", s = "tempest_xl_MR-68", c = "tempest_size2Xl_oLq5O", l = "tempest_size3Xl_YzlSH", u = "tempest_fullscreen_o84Xi", d = "tempest_fullscreenOnMobile_0bDwe", f = "tempest_body_lVhql", p = "tempest_header_ILG9i", m = "tempest_footer_rro2w", h = "tempest_title_A5OeE", g = "tempest_close_-ER1C", _ = {
|
|
4
4
|
overlay: e,
|
|
5
5
|
tempestFadeIn: t,
|
|
6
6
|
dialog: n,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.module.js","names":[],"sources":["../../../src/components/Modal/Modal.module.css"],"sourcesContent":[".overlay {\n position: fixed;\n inset: 0;\n background-color: rgba(15, 23, 42, 0.55);\n backdrop-filter: blur(2px);\n -webkit-backdrop-filter: blur(2px);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: max(var(--tempest-space-4), var(--tempest-safe-area-top))\n max(var(--tempest-space-4), var(--tempest-safe-area-right))\n max(var(--tempest-space-4), var(--tempest-safe-area-bottom))\n max(var(--tempest-space-4), var(--tempest-safe-area-left));\n z-index: var(--tempest-z-modal);\n animation: tempest-fade-in var(--tempest-duration-base) var(--tempest-ease-out);\n}\n\n.dialog {\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n border-radius: var(--tempest-radius-xl);\n box-shadow: var(--tempest-shadow-xl);\n width: 100%;\n max-height: 90vh;\n max-height: 90dvh;\n display: flex;\n flex-direction: column;\n animation: tempest-modal-in var(--tempest-duration-base) var(--tempest-ease-emphasized);\n}\n\n.sm {\n max-width: 400px;\n}\n.md {\n max-width: 560px;\n}\n.lg {\n max-width: 800px;\n}\n.xl {\n max-width: 1024px;\n}\n.
|
|
1
|
+
{"version":3,"file":"Modal.module.js","names":[],"sources":["../../../src/components/Modal/Modal.module.css"],"sourcesContent":[".overlay {\n position: fixed;\n inset: 0;\n background-color: rgba(15, 23, 42, 0.55);\n backdrop-filter: blur(2px);\n -webkit-backdrop-filter: blur(2px);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: max(var(--tempest-space-4), var(--tempest-safe-area-top))\n max(var(--tempest-space-4), var(--tempest-safe-area-right))\n max(var(--tempest-space-4), var(--tempest-safe-area-bottom))\n max(var(--tempest-space-4), var(--tempest-safe-area-left));\n z-index: var(--tempest-z-modal);\n animation: tempest-fade-in var(--tempest-duration-base) var(--tempest-ease-out);\n}\n\n.dialog {\n background-color: var(--tempest-bg);\n color: var(--tempest-text);\n border-radius: var(--tempest-radius-xl);\n box-shadow: var(--tempest-shadow-xl);\n width: 100%;\n max-height: 90vh;\n max-height: 90dvh;\n display: flex;\n flex-direction: column;\n animation: tempest-modal-in var(--tempest-duration-base) var(--tempest-ease-emphasized);\n}\n\n.sm {\n max-width: 400px;\n}\n.md {\n max-width: 560px;\n}\n.lg {\n max-width: 800px;\n}\n.xl {\n max-width: 1024px;\n}\n.size2Xl {\n max-width: 1280px;\n}\n.size3Xl {\n max-width: 1440px;\n}\n\n/* Fullscreen — fill entire viewport regardless of size. */\n.fullscreen {\n max-width: 100%;\n max-height: 100vh;\n max-height: 100dvh;\n width: 100%;\n height: 100%;\n border-radius: 0;\n}\n\n/* Auto-fullscreen below mobile breakpoint. */\n@media (max-width: 639.98px) {\n .fullscreenOnMobile {\n max-width: 100%;\n max-height: 100vh;\n max-height: 100dvh;\n width: 100%;\n height: 100%;\n border-radius: 0;\n }\n}\n\n/* Mobile padding adjustment for non-fullscreen modals. */\n@media (max-width: 639.98px) {\n .dialog:not(.fullscreen):not(.fullscreenOnMobile) {\n border-radius: var(--tempest-radius-lg);\n }\n .body {\n padding: var(--tempest-space-4);\n }\n .header,\n .footer {\n padding: var(--tempest-space-3) var(--tempest-space-4);\n }\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--tempest-space-3);\n padding: var(--tempest-space-4) var(--tempest-space-5);\n border-bottom: 1px solid var(--tempest-border);\n}\n\n.title {\n margin: 0;\n font-size: var(--tempest-text-lg);\n font-weight: var(--tempest-weight-semibold);\n line-height: var(--tempest-leading-snug);\n color: var(--tempest-text);\n}\n\n.close {\n background: none;\n border: none;\n color: var(--tempest-text-muted);\n padding: var(--tempest-space-1);\n border-radius: var(--tempest-radius-sm);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: var(--tempest-transition-color);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .close:hover {\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n }\n}\n\n.close:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: var(--tempest-focus-ring-offset);\n}\n\n.body {\n padding: var(--tempest-space-5);\n overflow-y: auto;\n line-height: var(--tempest-leading-normal);\n}\n\n.footer {\n display: flex;\n justify-content: flex-end;\n gap: var(--tempest-space-2);\n padding: var(--tempest-space-4) var(--tempest-space-5);\n border-top: 1px solid var(--tempest-border);\n background-color: var(--tempest-surface);\n border-radius: 0 0 var(--tempest-radius-xl) var(--tempest-radius-xl);\n}\n\n@keyframes tempest-fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n@keyframes tempest-modal-in {\n from {\n opacity: 0;\n transform: translateY(12px) scale(0.96);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .overlay,\n .dialog {\n animation: none;\n }\n}\n"],"mappings":";"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../../utils/cn.cjs"),t=require("./Page.module.cjs");let
|
|
1
|
+
const e=require("../../utils/cn.cjs"),t=require("../SectionHeader/SectionHeader.cjs"),n=require("./Page.module.cjs");let r=require("react/jsx-runtime");function i({title:i,eyebrow:a,description:o,actions:s,toolbar:c,footer:l,padded:u=!0,className:d,children:f,...p}){return(0,r.jsxs)(`main`,{className:e.cn(n.default.page,u&&n.default.padded,d),...p,children:[(0,r.jsx)(t.SectionHeader,{level:1,eyebrow:a,title:i,description:o,actions:s}),c&&(0,r.jsx)(`div`,{className:n.default.toolbar,children:c}),(0,r.jsx)(`div`,{className:n.default.content,children:f}),l&&(0,r.jsx)(`footer`,{className:n.default.footer,children:l})]})}exports.Page=i;
|
|
2
2
|
//# sourceMappingURL=Page.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Page.cjs","names":[],"sources":["../../../src/components/Page/Page.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — a page shell is slots: eyebrow, title, description,\n * actions, toolbar, footer and children, with padded as the one behavioural switch.\n * Slots are the component.\n */\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Page.module.css\";\n\nexport interface PageProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n /** Page title rendered as `<h1>`. */\n title?: ReactNode;\n /** Optional subtitle / breadcrumbs slot rendered above the title. */\n eyebrow?: ReactNode;\n /** Optional description rendered below the title. */\n description?: ReactNode;\n /** Right-side actions slot in the header (buttons, menus). */\n actions?: ReactNode;\n /** Sticky tab bar / filter row rendered just below the header. */\n toolbar?: ReactNode;\n /** Footer slot rendered at the bottom of the content area. */\n footer?: ReactNode;\n /** Page-level padding. Default `true`. */\n padded?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Page wrapper with header + (optional) toolbar + content + footer. Pairs\n * with `Container` when you want a max-width content well.\n *\n * @example\n * <Page title=\"Pedidos\" description=\"Acompanhe seus pedidos\" actions={<Button>Novo</Button>}>\n * <Table {...} />\n * </Page>\n */\nexport function Page({\n title,\n eyebrow,\n description,\n actions,\n toolbar,\n footer,\n padded = true,\n className,\n children,\n ...props\n}: PageProps) {\n
|
|
1
|
+
{"version":3,"file":"Page.cjs","names":[],"sources":["../../../src/components/Page/Page.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — a page shell is slots: eyebrow, title, description,\n * actions, toolbar, footer and children, with padded as the one behavioural switch.\n * Slots are the component.\n */\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { SectionHeader } from \"../SectionHeader\";\nimport styles from \"./Page.module.css\";\n\nexport interface PageProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n /** Page title rendered as `<h1>`. */\n title?: ReactNode;\n /** Optional subtitle / breadcrumbs slot rendered above the title. */\n eyebrow?: ReactNode;\n /** Optional description rendered below the title. */\n description?: ReactNode;\n /** Right-side actions slot in the header (buttons, menus). */\n actions?: ReactNode;\n /** Sticky tab bar / filter row rendered just below the header. */\n toolbar?: ReactNode;\n /** Footer slot rendered at the bottom of the content area. */\n footer?: ReactNode;\n /** Page-level padding. Default `true`. */\n padded?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Page wrapper with header + (optional) toolbar + content + footer. Pairs\n * with `Container` when you want a max-width content well.\n *\n * The header is a `SectionHeader` at `level={1}`, so the page title and the\n * `<h2>` of each section below it share one look; when every header slot is\n * empty no `<header>` is rendered.\n *\n * @example\n * <Page title=\"Pedidos\" description=\"Acompanhe seus pedidos\" actions={<Button>Novo</Button>}>\n * <Table {...} />\n * </Page>\n */\nexport function Page({\n title,\n eyebrow,\n description,\n actions,\n toolbar,\n footer,\n padded = true,\n className,\n children,\n ...props\n}: PageProps) {\n return (\n <main className={cn(styles.page, padded && styles.padded, className)} {...props}>\n <SectionHeader\n level={1}\n eyebrow={eyebrow}\n title={title}\n description={description}\n actions={actions}\n />\n {toolbar && <div className={styles.toolbar}>{toolbar}</div>}\n <div className={styles.content}>{children}</div>\n {footer && <footer className={styles.footer}>{footer}</footer>}\n </main>\n );\n}\n"],"mappings":"wJAyCA,SAAgB,EAAK,CACjB,QACA,UACA,cACA,UACA,UACA,SACA,SAAS,GACT,YACA,WACA,GAAG,GACO,CACV,OACI,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,GAAU,EAAA,QAAO,OAAQ,CAAS,EAAG,GAAI,EAA1E,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,EAAA,cAAD,CACI,MAAO,EACE,UACF,QACM,cACJ,SACZ,CAAA,EACA,IAAW,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,QAAU,SAAA,CAAa,CAAA,GAC1D,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,QAAU,UAAc,CAAA,EAC9C,IAAU,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,UAAW,EAAA,QAAO,OAAS,SAAA,CAAe,CAAA,CAC3D,GAEd"}
|
|
@@ -1,52 +1,36 @@
|
|
|
1
1
|
import { cn as e } from "../../utils/cn.js";
|
|
2
|
-
import t from "
|
|
3
|
-
import
|
|
2
|
+
import { SectionHeader as t } from "../SectionHeader/SectionHeader.js";
|
|
3
|
+
import n from "./Page.module.js";
|
|
4
|
+
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
4
5
|
//#region src/components/Page/Page.tsx
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
...p,
|
|
6
|
+
function a({ title: a, eyebrow: o, description: s, actions: c, toolbar: l, footer: u, padded: d = !0, className: f, children: p, ...m }) {
|
|
7
|
+
return /* @__PURE__ */ i("main", {
|
|
8
|
+
className: e(n.page, d && n.padded, f),
|
|
9
|
+
...m,
|
|
10
10
|
children: [
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
className: t.eyebrow,
|
|
18
|
-
children: a
|
|
19
|
-
}),
|
|
20
|
-
i && /* @__PURE__ */ n("h1", {
|
|
21
|
-
className: t.title,
|
|
22
|
-
children: i
|
|
23
|
-
}),
|
|
24
|
-
o && /* @__PURE__ */ n("p", {
|
|
25
|
-
className: t.description,
|
|
26
|
-
children: o
|
|
27
|
-
})
|
|
28
|
-
]
|
|
29
|
-
}), s && /* @__PURE__ */ n("div", {
|
|
30
|
-
className: t.actions,
|
|
31
|
-
children: s
|
|
32
|
-
})]
|
|
11
|
+
/* @__PURE__ */ r(t, {
|
|
12
|
+
level: 1,
|
|
13
|
+
eyebrow: o,
|
|
14
|
+
title: a,
|
|
15
|
+
description: s,
|
|
16
|
+
actions: c
|
|
33
17
|
}),
|
|
34
|
-
|
|
35
|
-
className:
|
|
36
|
-
children:
|
|
18
|
+
l && /* @__PURE__ */ r("div", {
|
|
19
|
+
className: n.toolbar,
|
|
20
|
+
children: l
|
|
37
21
|
}),
|
|
38
|
-
/* @__PURE__ */
|
|
39
|
-
className:
|
|
40
|
-
children:
|
|
22
|
+
/* @__PURE__ */ r("div", {
|
|
23
|
+
className: n.content,
|
|
24
|
+
children: p
|
|
41
25
|
}),
|
|
42
|
-
|
|
43
|
-
className:
|
|
44
|
-
children:
|
|
26
|
+
u && /* @__PURE__ */ r("footer", {
|
|
27
|
+
className: n.footer,
|
|
28
|
+
children: u
|
|
45
29
|
})
|
|
46
30
|
]
|
|
47
31
|
});
|
|
48
32
|
}
|
|
49
33
|
//#endregion
|
|
50
|
-
export {
|
|
34
|
+
export { a as Page };
|
|
51
35
|
|
|
52
36
|
//# sourceMappingURL=Page.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Page.js","names":[],"sources":["../../../src/components/Page/Page.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — a page shell is slots: eyebrow, title, description,\n * actions, toolbar, footer and children, with padded as the one behavioural switch.\n * Slots are the component.\n */\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Page.module.css\";\n\nexport interface PageProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n /** Page title rendered as `<h1>`. */\n title?: ReactNode;\n /** Optional subtitle / breadcrumbs slot rendered above the title. */\n eyebrow?: ReactNode;\n /** Optional description rendered below the title. */\n description?: ReactNode;\n /** Right-side actions slot in the header (buttons, menus). */\n actions?: ReactNode;\n /** Sticky tab bar / filter row rendered just below the header. */\n toolbar?: ReactNode;\n /** Footer slot rendered at the bottom of the content area. */\n footer?: ReactNode;\n /** Page-level padding. Default `true`. */\n padded?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Page wrapper with header + (optional) toolbar + content + footer. Pairs\n * with `Container` when you want a max-width content well.\n *\n * @example\n * <Page title=\"Pedidos\" description=\"Acompanhe seus pedidos\" actions={<Button>Novo</Button>}>\n * <Table {...} />\n * </Page>\n */\nexport function Page({\n title,\n eyebrow,\n description,\n actions,\n toolbar,\n footer,\n padded = true,\n className,\n children,\n ...props\n}: PageProps) {\n
|
|
1
|
+
{"version":3,"file":"Page.js","names":[],"sources":["../../../src/components/Page/Page.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — a page shell is slots: eyebrow, title, description,\n * actions, toolbar, footer and children, with padded as the one behavioural switch.\n * Slots are the component.\n */\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { SectionHeader } from \"../SectionHeader\";\nimport styles from \"./Page.module.css\";\n\nexport interface PageProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n /** Page title rendered as `<h1>`. */\n title?: ReactNode;\n /** Optional subtitle / breadcrumbs slot rendered above the title. */\n eyebrow?: ReactNode;\n /** Optional description rendered below the title. */\n description?: ReactNode;\n /** Right-side actions slot in the header (buttons, menus). */\n actions?: ReactNode;\n /** Sticky tab bar / filter row rendered just below the header. */\n toolbar?: ReactNode;\n /** Footer slot rendered at the bottom of the content area. */\n footer?: ReactNode;\n /** Page-level padding. Default `true`. */\n padded?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Page wrapper with header + (optional) toolbar + content + footer. Pairs\n * with `Container` when you want a max-width content well.\n *\n * The header is a `SectionHeader` at `level={1}`, so the page title and the\n * `<h2>` of each section below it share one look; when every header slot is\n * empty no `<header>` is rendered.\n *\n * @example\n * <Page title=\"Pedidos\" description=\"Acompanhe seus pedidos\" actions={<Button>Novo</Button>}>\n * <Table {...} />\n * </Page>\n */\nexport function Page({\n title,\n eyebrow,\n description,\n actions,\n toolbar,\n footer,\n padded = true,\n className,\n children,\n ...props\n}: PageProps) {\n return (\n <main className={cn(styles.page, padded && styles.padded, className)} {...props}>\n <SectionHeader\n level={1}\n eyebrow={eyebrow}\n title={title}\n description={description}\n actions={actions}\n />\n {toolbar && <div className={styles.toolbar}>{toolbar}</div>}\n <div className={styles.content}>{children}</div>\n {footer && <footer className={styles.footer}>{footer}</footer>}\n </main>\n );\n}\n"],"mappings":";;;;;AAyCA,SAAgB,EAAK,EACjB,UACA,YACA,gBACA,YACA,YACA,WACA,YAAS,IACT,cACA,aACA,GAAG,KACO;CACV,OACI,kBAAC,QAAD;EAAM,WAAW,EAAG,EAAO,MAAM,KAAU,EAAO,QAAQ,CAAS;EAAG,GAAI;EAA1E,UAAA;GACI,kBAAC,GAAD;IACI,OAAO;IACE;IACF;IACM;IACJ;GACZ,CAAA;GACA,KAAW,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAU,UAAA;GAAa,CAAA;GAC1D,kBAAC,OAAD;IAAK,WAAW,EAAO;IAAU;GAAc,CAAA;GAC9C,KAAU,kBAAC,UAAD;IAAQ,WAAW,EAAO;IAAS,UAAA;GAAe,CAAA;EAC3D;;AAEd"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
require("../../styles/component/Page.css");
|
|
2
|
-
var e=`tempest_page_THNNc`,t=`tempest_padded_bzjoF`,n=`
|
|
2
|
+
var e=`tempest_page_THNNc`,t=`tempest_padded_bzjoF`,n=`tempest_toolbar_sA7sD`,r=`tempest_content_RCB4b`,i=`tempest_footer_540pQ`,a={page:e,padded:t,toolbar:n,content:r,footer:i};exports.content=r,exports.default=a,exports.footer=i,exports.padded=t,exports.page=e,exports.toolbar=n;
|
|
3
3
|
//# sourceMappingURL=Page.module.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Page.module.cjs","names":[],"sources":["../../../src/components/Page/Page.module.css"],"sourcesContent":[".page {\n display: flex;\n flex-direction: column;\n width: 100%;\n min-height: 100%;\n font-family: var(--tempest-font-sans);\n color: var(--tempest-text);\n}\n\n.padded {\n padding: var(--tempest-space-5) var(--tempest-space-4);\n}\n\n@media (min-width: 768px) {\n .padded {\n padding: var(--tempest-space-6) var(--tempest-space-6);\n }\n}\n\n.
|
|
1
|
+
{"version":3,"file":"Page.module.cjs","names":[],"sources":["../../../src/components/Page/Page.module.css"],"sourcesContent":[".page {\n display: flex;\n flex-direction: column;\n width: 100%;\n min-height: 100%;\n font-family: var(--tempest-font-sans);\n color: var(--tempest-text);\n}\n\n.padded {\n padding: var(--tempest-space-5) var(--tempest-space-4);\n}\n\n@media (min-width: 768px) {\n .padded {\n padding: var(--tempest-space-6) var(--tempest-space-6);\n }\n}\n\n.toolbar {\n margin-bottom: var(--tempest-space-4);\n}\n\n.content {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.footer {\n margin-top: var(--tempest-space-6);\n padding-top: var(--tempest-space-4);\n border-top: 1px solid var(--tempest-border);\n}\n"],"mappings":";"}
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
import "../../styles/component/Page.css";
|
|
2
2
|
//#region src/components/Page/Page.module.css
|
|
3
|
-
var e = "tempest_page_THNNc", t = "tempest_padded_bzjoF", n = "
|
|
3
|
+
var e = "tempest_page_THNNc", t = "tempest_padded_bzjoF", n = "tempest_toolbar_sA7sD", r = "tempest_content_RCB4b", i = "tempest_footer_540pQ", a = {
|
|
4
4
|
page: e,
|
|
5
5
|
padded: t,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
title: a,
|
|
10
|
-
description: o,
|
|
11
|
-
actions: s,
|
|
12
|
-
toolbar: c,
|
|
13
|
-
content: l,
|
|
14
|
-
footer: u
|
|
6
|
+
toolbar: n,
|
|
7
|
+
content: r,
|
|
8
|
+
footer: i
|
|
15
9
|
};
|
|
16
10
|
//#endregion
|
|
17
|
-
export {
|
|
11
|
+
export { r as content, a as default, i as footer, t as padded, e as page, n as toolbar };
|
|
18
12
|
|
|
19
13
|
//# sourceMappingURL=Page.module.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Page.module.js","names":[],"sources":["../../../src/components/Page/Page.module.css"],"sourcesContent":[".page {\n display: flex;\n flex-direction: column;\n width: 100%;\n min-height: 100%;\n font-family: var(--tempest-font-sans);\n color: var(--tempest-text);\n}\n\n.padded {\n padding: var(--tempest-space-5) var(--tempest-space-4);\n}\n\n@media (min-width: 768px) {\n .padded {\n padding: var(--tempest-space-6) var(--tempest-space-6);\n }\n}\n\n.
|
|
1
|
+
{"version":3,"file":"Page.module.js","names":[],"sources":["../../../src/components/Page/Page.module.css"],"sourcesContent":[".page {\n display: flex;\n flex-direction: column;\n width: 100%;\n min-height: 100%;\n font-family: var(--tempest-font-sans);\n color: var(--tempest-text);\n}\n\n.padded {\n padding: var(--tempest-space-5) var(--tempest-space-4);\n}\n\n@media (min-width: 768px) {\n .padded {\n padding: var(--tempest-space-6) var(--tempest-space-6);\n }\n}\n\n.toolbar {\n margin-bottom: var(--tempest-space-4);\n}\n\n.content {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.footer {\n margin-top: var(--tempest-space-6);\n padding-top: var(--tempest-space-4);\n border-top: 1px solid var(--tempest-border);\n}\n"],"mappings":";"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../../utils/cn.cjs"),t=require("../../hooks/use-intersection-observer.cjs"),n=require("./reveal-threshold.cjs"),r=require("./Reveal.module.cjs");let i=require("react"),a=require("react/jsx-runtime");var o={current:null};function s(){return()=>void 0}function c(){return typeof IntersectionObserver<`u`}function l(){return!1}function u({as:u=`div`,variant:d=`up`,delay:f,duration:p,once:m=!0,threshold:h=.15,rootMargin:g=`0px`,className:_,style:v,children:y,...b}){let x=(0,i.useRef)(null),S=(0,i.useSyncExternalStore)(s,c,l),[C,w]=(0,i.useState)(!1),[T,E]=(0,i.useState)({requested:h,value:h}),D=T.requested===h?T.value:h,O=t.useIntersectionObserver(S&&!(m&&C)?x:o,{rootMargin:g,threshold:D});(0,i.useEffect)(()=>{if(!O)return;let e=n.effectiveThreshold(h,O);Math.abs(e-D)>.001&&E({requested:h,value:e}),O.isIntersecting&&O.intersectionRatio+.001>=e?w(!0):!m&&!O.isIntersecting&&w(!1)},[O,h,D,m]);let k=S?C?`shown`:`hidden`:`static`,A={};return f!==void 0&&(A[`--tempest-reveal-delay`]=`${f}ms`),p!==void 0&&(A[`--tempest-reveal-duration`]=`${p}ms`),(0,a.jsx)(u,{...b,ref:x,className:e.cn(r.default.reveal,_),style:{...A,...v},"data-state":k,"data-variant":d,children:y})}exports.Reveal=u;
|
|
2
|
+
//# sourceMappingURL=Reveal.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Reveal.cjs","names":[],"sources":["../../../src/components/Reveal/Reveal.tsx"],"sourcesContent":["import type { CSSProperties, ElementType, HTMLAttributes, JSX, RefObject } from \"react\";\nimport { useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { useIntersectionObserver } from \"@/hooks/use-intersection-observer\";\nimport { cn } from \"@/utils/cn\";\nimport { RATIO_EPSILON, effectiveThreshold } from \"./reveal-threshold\";\nimport styles from \"./Reveal.module.css\";\n\n/** Direction the content travels from, or `\"fade\"` / `\"scale\"` for no travel. */\nexport type RevealVariant = \"fade\" | \"up\" | \"down\" | \"left\" | \"right\" | \"scale\";\n\n/** Visual state written to `data-state`. */\nexport type RevealState = \"static\" | \"hidden\" | \"shown\";\n\nexport interface RevealProps extends HTMLAttributes<HTMLElement> {\n /** Intrinsic element to render, e.g. `\"li\"` inside a list. Defaults to `\"div\"`. */\n as?: keyof JSX.IntrinsicElements;\n /** How the content enters. Defaults to `\"up\"`. */\n variant?: RevealVariant;\n /** Wait before the entrance starts, in ms. Stagger siblings with `index * step`. */\n delay?: number;\n /** Length of the entrance, in ms. Defaults to `--tempest-duration-slower`. */\n duration?: number;\n /** Reveal once and stop observing. With `false`, it hides again once fully out of view. Defaults to `true`. */\n once?: boolean;\n /**\n * Fraction of the element — or of the viewport, when the element is taller\n * than it — that must be visible to reveal. Defaults to `0.15`.\n */\n threshold?: number;\n /** Margin around the root, as in `IntersectionObserver`. Defaults to `\"0px\"`. */\n rootMargin?: string;\n}\n\n/** A ref that never points at an element, used to switch the observer off. */\nconst DETACHED: RefObject<Element | null> = { current: null };\n\n/**\n * Subscribe function for a snapshot that never changes after mount.\n *\n * @returns A no-op unsubscribe.\n */\nfunction subscribeNever(): () => void {\n return () => undefined;\n}\n\n/**\n * Whether this environment can observe intersections.\n *\n * @returns `true` when `IntersectionObserver` exists.\n */\nfunction canObserve(): boolean {\n return typeof IntersectionObserver !== \"undefined\";\n}\n\n/**\n * Server snapshot: never hide content that was rendered without JavaScript.\n *\n * @returns Always `false`.\n */\nfunction cannotObserve(): boolean {\n return false;\n}\n\n/**\n * Animate content into view the first time it is scrolled to.\n *\n * The three failure modes of a hand-rolled version are handled here, not left to\n * the docs:\n *\n * - **Reduced motion.** Under `prefers-reduced-motion: reduce` the stylesheet\n * pins the element visible with no transform and no transition, whatever\n * state it is in — so the setting also wins when it changes mid-session.\n * - **No `IntersectionObserver`** (old engines, some crawlers, tests): the\n * element stays in the `\"static\"` state, which is plain visible content. It is\n * never hidden waiting for an observation that cannot come.\n * - **Taller than the viewport.** A box three viewports tall never reaches a\n * ratio of 0.5, so a raw observer with that threshold never reveals it. The\n * threshold is rescaled by the highest ratio the element can reach (see\n * `effectiveThreshold`), read from the first observation.\n *\n * Content is hidden only when the client can observe: the server snapshot of\n * `useSyncExternalStore` is `\"static\"`, so markup rendered without JavaScript —\n * or before hydration — is visible. The transition is declared on the `\"shown\"`\n * state only, so the switch to `\"hidden\"` on mount is instant instead of a\n * fade-out, and with `once={false}` leaving the viewport hides without motion.\n *\n * With `once={false}` the element hides only once it is fully out of view. Hiding\n * on the threshold would oscillate: the hidden state translates the box, which\n * moves it back across the same threshold.\n *\n * @example\n * <ul>\n * {steps.map((step, index) => (\n * <Reveal key={step.id} as=\"li\" delay={index * 80}>\n * {step.title}\n * </Reveal>\n * ))}\n * </ul>\n */\nexport function Reveal({\n as = \"div\",\n variant = \"up\",\n delay,\n duration,\n once = true,\n threshold = 0.15,\n rootMargin = \"0px\",\n className,\n style,\n children,\n ...props\n}: RevealProps) {\n const ref = useRef<HTMLElement>(null);\n const observable = useSyncExternalStore(subscribeNever, canObserve, cannotObserve);\n const [shown, setShown] = useState<boolean>(false);\n const [rescaled, setRescaled] = useState<{ requested: number; value: number }>({\n requested: threshold,\n value: threshold,\n });\n const observeAt = rescaled.requested === threshold ? rescaled.value : threshold;\n const settled = once && shown;\n\n const entry = useIntersectionObserver(observable && !settled ? ref : DETACHED, {\n rootMargin,\n threshold: observeAt,\n });\n\n useEffect(() => {\n if (!entry) return;\n const target = effectiveThreshold(threshold, entry);\n if (Math.abs(target - observeAt) > RATIO_EPSILON) {\n setRescaled({ requested: threshold, value: target });\n }\n if (entry.isIntersecting && entry.intersectionRatio + RATIO_EPSILON >= target) {\n setShown(true);\n } else if (!once && !entry.isIntersecting) {\n setShown(false);\n }\n }, [entry, threshold, observeAt, once]);\n\n const state: RevealState = !observable ? \"static\" : shown ? \"shown\" : \"hidden\";\n const timing: Record<string, string> = {};\n if (delay !== undefined) timing[\"--tempest-reveal-delay\"] = `${delay}ms`;\n if (duration !== undefined) timing[\"--tempest-reveal-duration\"] = `${duration}ms`;\n\n const Tag = as as ElementType;\n\n return (\n <Tag\n {...props}\n ref={ref}\n className={cn(styles.reveal, className)}\n style={{ ...timing, ...style } as CSSProperties}\n data-state={state}\n data-variant={variant}\n >\n {children}\n </Tag>\n );\n}\n"],"mappings":"wNAkCA,IAAM,EAAsC,CAAE,QAAS,IAAK,EAO5D,SAAS,GAA6B,CAClC,UAAa,IAAA,EACjB,CAOA,SAAS,GAAsB,CAC3B,OAAO,OAAO,qBAAyB,GAC3C,CAOA,SAAS,GAAyB,CAC9B,MAAO,EACX,CAsCA,SAAgB,EAAO,CACnB,KAAK,MACL,UAAU,KACV,QACA,WACA,OAAO,GACP,YAAY,IACZ,aAAa,MACb,YACA,QACA,WACA,GAAG,GACS,CACZ,IAAM,GAAA,EAAM,EAAA,OAAA,CAAoB,IAAI,EAC9B,GAAA,EAAa,EAAA,qBAAA,CAAqB,EAAgB,EAAY,CAAa,EAC3E,CAAC,EAAO,IAAA,EAAY,EAAA,SAAA,CAAkB,EAAK,EAC3C,CAAC,EAAU,IAAA,EAAe,EAAA,SAAA,CAA+C,CAC3E,UAAW,EACX,MAAO,CACX,CAAC,EACK,EAAY,EAAS,YAAc,EAAY,EAAS,MAAQ,EAGhE,EAAQ,EAAA,wBAAwB,GAAc,EAFpC,GAAQ,GAEuC,EAAM,EAAU,CAC3E,aACA,UAAW,CACf,CAAC,GAED,EAAA,EAAA,UAAA,KAAgB,CACZ,GAAI,CAAC,EAAO,OACZ,IAAM,EAAS,EAAA,mBAAmB,EAAW,CAAK,EAC9C,KAAK,IAAI,EAAS,CAAS,EAAA,MAC3B,EAAY,CAAE,UAAW,EAAW,MAAO,CAAO,CAAC,EAEnD,EAAM,gBAAkB,EAAM,kBAAA,MAAqC,EACnE,EAAS,EAAI,EACN,CAAC,GAAQ,CAAC,EAAM,gBACvB,EAAS,EAAK,CAEtB,EAAG,CAAC,EAAO,EAAW,EAAW,CAAI,CAAC,EAEtC,IAAM,EAAsB,EAAwB,EAAQ,QAAU,SAA7B,SACnC,EAAiC,CAAC,EAMxC,OALI,IAAU,IAAA,KAAW,EAAO,0BAA4B,GAAG,EAAM,KACjE,IAAa,IAAA,KAAW,EAAO,6BAA+B,GAAG,EAAS,MAK1E,EAAA,EAAA,IAAA,CAAC,EAAD,CACI,GAAI,EACC,MACL,UAAW,EAAA,GAAG,EAAA,QAAO,OAAQ,CAAS,EACtC,MAAO,CAAE,GAAG,EAAQ,GAAG,CAAM,EAC7B,aAAY,EACZ,eAAc,EAEb,UACA,CAAA,CAEb"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { cn as e } from "../../utils/cn.js";
|
|
2
|
+
import { useIntersectionObserver as t } from "../../hooks/use-intersection-observer.js";
|
|
3
|
+
import { effectiveThreshold as n } from "./reveal-threshold.js";
|
|
4
|
+
import r from "./Reveal.module.js";
|
|
5
|
+
import { useEffect as i, useRef as a, useState as o, useSyncExternalStore as s } from "react";
|
|
6
|
+
import { jsx as c } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/Reveal/Reveal.tsx
|
|
8
|
+
var l = { current: null };
|
|
9
|
+
function u() {
|
|
10
|
+
return () => void 0;
|
|
11
|
+
}
|
|
12
|
+
function d() {
|
|
13
|
+
return typeof IntersectionObserver < "u";
|
|
14
|
+
}
|
|
15
|
+
function f() {
|
|
16
|
+
return !1;
|
|
17
|
+
}
|
|
18
|
+
function p({ as: p = "div", variant: m = "up", delay: h, duration: g, once: _ = !0, threshold: v = .15, rootMargin: y = "0px", className: b, style: x, children: S, ...C }) {
|
|
19
|
+
let w = a(null), T = s(u, d, f), [E, D] = o(!1), [O, k] = o({
|
|
20
|
+
requested: v,
|
|
21
|
+
value: v
|
|
22
|
+
}), A = O.requested === v ? O.value : v, j = t(T && !(_ && E) ? w : l, {
|
|
23
|
+
rootMargin: y,
|
|
24
|
+
threshold: A
|
|
25
|
+
});
|
|
26
|
+
i(() => {
|
|
27
|
+
if (!j) return;
|
|
28
|
+
let e = n(v, j);
|
|
29
|
+
Math.abs(e - A) > .001 && k({
|
|
30
|
+
requested: v,
|
|
31
|
+
value: e
|
|
32
|
+
}), j.isIntersecting && j.intersectionRatio + .001 >= e ? D(!0) : !_ && !j.isIntersecting && D(!1);
|
|
33
|
+
}, [
|
|
34
|
+
j,
|
|
35
|
+
v,
|
|
36
|
+
A,
|
|
37
|
+
_
|
|
38
|
+
]);
|
|
39
|
+
let M = T ? E ? "shown" : "hidden" : "static", N = {};
|
|
40
|
+
return h !== void 0 && (N["--tempest-reveal-delay"] = `${h}ms`), g !== void 0 && (N["--tempest-reveal-duration"] = `${g}ms`), /* @__PURE__ */ c(p, {
|
|
41
|
+
...C,
|
|
42
|
+
ref: w,
|
|
43
|
+
className: e(r.reveal, b),
|
|
44
|
+
style: {
|
|
45
|
+
...N,
|
|
46
|
+
...x
|
|
47
|
+
},
|
|
48
|
+
"data-state": M,
|
|
49
|
+
"data-variant": m,
|
|
50
|
+
children: S
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { p as Reveal };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=Reveal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Reveal.js","names":[],"sources":["../../../src/components/Reveal/Reveal.tsx"],"sourcesContent":["import type { CSSProperties, ElementType, HTMLAttributes, JSX, RefObject } from \"react\";\nimport { useEffect, useRef, useState, useSyncExternalStore } from \"react\";\nimport { useIntersectionObserver } from \"@/hooks/use-intersection-observer\";\nimport { cn } from \"@/utils/cn\";\nimport { RATIO_EPSILON, effectiveThreshold } from \"./reveal-threshold\";\nimport styles from \"./Reveal.module.css\";\n\n/** Direction the content travels from, or `\"fade\"` / `\"scale\"` for no travel. */\nexport type RevealVariant = \"fade\" | \"up\" | \"down\" | \"left\" | \"right\" | \"scale\";\n\n/** Visual state written to `data-state`. */\nexport type RevealState = \"static\" | \"hidden\" | \"shown\";\n\nexport interface RevealProps extends HTMLAttributes<HTMLElement> {\n /** Intrinsic element to render, e.g. `\"li\"` inside a list. Defaults to `\"div\"`. */\n as?: keyof JSX.IntrinsicElements;\n /** How the content enters. Defaults to `\"up\"`. */\n variant?: RevealVariant;\n /** Wait before the entrance starts, in ms. Stagger siblings with `index * step`. */\n delay?: number;\n /** Length of the entrance, in ms. Defaults to `--tempest-duration-slower`. */\n duration?: number;\n /** Reveal once and stop observing. With `false`, it hides again once fully out of view. Defaults to `true`. */\n once?: boolean;\n /**\n * Fraction of the element — or of the viewport, when the element is taller\n * than it — that must be visible to reveal. Defaults to `0.15`.\n */\n threshold?: number;\n /** Margin around the root, as in `IntersectionObserver`. Defaults to `\"0px\"`. */\n rootMargin?: string;\n}\n\n/** A ref that never points at an element, used to switch the observer off. */\nconst DETACHED: RefObject<Element | null> = { current: null };\n\n/**\n * Subscribe function for a snapshot that never changes after mount.\n *\n * @returns A no-op unsubscribe.\n */\nfunction subscribeNever(): () => void {\n return () => undefined;\n}\n\n/**\n * Whether this environment can observe intersections.\n *\n * @returns `true` when `IntersectionObserver` exists.\n */\nfunction canObserve(): boolean {\n return typeof IntersectionObserver !== \"undefined\";\n}\n\n/**\n * Server snapshot: never hide content that was rendered without JavaScript.\n *\n * @returns Always `false`.\n */\nfunction cannotObserve(): boolean {\n return false;\n}\n\n/**\n * Animate content into view the first time it is scrolled to.\n *\n * The three failure modes of a hand-rolled version are handled here, not left to\n * the docs:\n *\n * - **Reduced motion.** Under `prefers-reduced-motion: reduce` the stylesheet\n * pins the element visible with no transform and no transition, whatever\n * state it is in — so the setting also wins when it changes mid-session.\n * - **No `IntersectionObserver`** (old engines, some crawlers, tests): the\n * element stays in the `\"static\"` state, which is plain visible content. It is\n * never hidden waiting for an observation that cannot come.\n * - **Taller than the viewport.** A box three viewports tall never reaches a\n * ratio of 0.5, so a raw observer with that threshold never reveals it. The\n * threshold is rescaled by the highest ratio the element can reach (see\n * `effectiveThreshold`), read from the first observation.\n *\n * Content is hidden only when the client can observe: the server snapshot of\n * `useSyncExternalStore` is `\"static\"`, so markup rendered without JavaScript —\n * or before hydration — is visible. The transition is declared on the `\"shown\"`\n * state only, so the switch to `\"hidden\"` on mount is instant instead of a\n * fade-out, and with `once={false}` leaving the viewport hides without motion.\n *\n * With `once={false}` the element hides only once it is fully out of view. Hiding\n * on the threshold would oscillate: the hidden state translates the box, which\n * moves it back across the same threshold.\n *\n * @example\n * <ul>\n * {steps.map((step, index) => (\n * <Reveal key={step.id} as=\"li\" delay={index * 80}>\n * {step.title}\n * </Reveal>\n * ))}\n * </ul>\n */\nexport function Reveal({\n as = \"div\",\n variant = \"up\",\n delay,\n duration,\n once = true,\n threshold = 0.15,\n rootMargin = \"0px\",\n className,\n style,\n children,\n ...props\n}: RevealProps) {\n const ref = useRef<HTMLElement>(null);\n const observable = useSyncExternalStore(subscribeNever, canObserve, cannotObserve);\n const [shown, setShown] = useState<boolean>(false);\n const [rescaled, setRescaled] = useState<{ requested: number; value: number }>({\n requested: threshold,\n value: threshold,\n });\n const observeAt = rescaled.requested === threshold ? rescaled.value : threshold;\n const settled = once && shown;\n\n const entry = useIntersectionObserver(observable && !settled ? ref : DETACHED, {\n rootMargin,\n threshold: observeAt,\n });\n\n useEffect(() => {\n if (!entry) return;\n const target = effectiveThreshold(threshold, entry);\n if (Math.abs(target - observeAt) > RATIO_EPSILON) {\n setRescaled({ requested: threshold, value: target });\n }\n if (entry.isIntersecting && entry.intersectionRatio + RATIO_EPSILON >= target) {\n setShown(true);\n } else if (!once && !entry.isIntersecting) {\n setShown(false);\n }\n }, [entry, threshold, observeAt, once]);\n\n const state: RevealState = !observable ? \"static\" : shown ? \"shown\" : \"hidden\";\n const timing: Record<string, string> = {};\n if (delay !== undefined) timing[\"--tempest-reveal-delay\"] = `${delay}ms`;\n if (duration !== undefined) timing[\"--tempest-reveal-duration\"] = `${duration}ms`;\n\n const Tag = as as ElementType;\n\n return (\n <Tag\n {...props}\n ref={ref}\n className={cn(styles.reveal, className)}\n style={{ ...timing, ...style } as CSSProperties}\n data-state={state}\n data-variant={variant}\n >\n {children}\n </Tag>\n );\n}\n"],"mappings":";;;;;;;AAkCA,IAAM,IAAsC,EAAE,SAAS,KAAK;AAO5D,SAAS,IAA6B;CAClC,aAAa,KAAA;AACjB;AAOA,SAAS,IAAsB;CAC3B,OAAO,OAAO,uBAAyB;AAC3C;AAOA,SAAS,IAAyB;CAC9B,OAAO;AACX;AAsCA,SAAgB,EAAO,EACnB,QAAK,OACL,aAAU,MACV,UACA,aACA,UAAO,IACP,eAAY,KACZ,gBAAa,OACb,cACA,UACA,aACA,GAAG,KACS;CACZ,IAAM,IAAM,EAAoB,IAAI,GAC9B,IAAa,EAAqB,GAAgB,GAAY,CAAa,GAC3E,CAAC,GAAO,KAAY,EAAkB,EAAK,GAC3C,CAAC,GAAU,KAAe,EAA+C;EAC3E,WAAW;EACX,OAAO;CACX,CAAC,GACK,IAAY,EAAS,cAAc,IAAY,EAAS,QAAQ,GAGhE,IAAQ,EAAwB,KAAc,EAFpC,KAAQ,KAEuC,IAAM,GAAU;EAC3E;EACA,WAAW;CACf,CAAC;CAED,QAAgB;EACZ,IAAI,CAAC,GAAO;EACZ,IAAM,IAAS,EAAmB,GAAW,CAAK;EAIlD,AAHI,KAAK,IAAI,IAAS,CAAS,IAAA,QAC3B,EAAY;GAAE,WAAW;GAAW,OAAO;EAAO,CAAC,GAEnD,EAAM,kBAAkB,EAAM,oBAAA,QAAqC,IACnE,EAAS,EAAI,IACN,CAAC,KAAQ,CAAC,EAAM,kBACvB,EAAS,EAAK;CAEtB,GAAG;EAAC;EAAO;EAAW;EAAW;CAAI,CAAC;CAEtC,IAAM,IAAsB,IAAwB,IAAQ,UAAU,WAA7B,UACnC,IAAiC,CAAC;CAMxC,OALI,MAAU,KAAA,MAAW,EAAO,4BAA4B,GAAG,EAAM,MACjE,MAAa,KAAA,MAAW,EAAO,+BAA+B,GAAG,EAAS,MAK1E,kBAAC,GAAD;EACI,GAAI;EACC;EACL,WAAW,EAAG,EAAO,QAAQ,CAAS;EACtC,OAAO;GAAE,GAAG;GAAQ,GAAG;EAAM;EAC7B,cAAY;EACZ,gBAAc;EAEb;CACA,CAAA;AAEb"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Reveal.module.cjs","names":[],"sources":["../../../src/components/Reveal/Reveal.module.css"],"sourcesContent":[".reveal[data-state=\"hidden\"] {\n opacity: 0;\n}\n\n.reveal[data-state=\"hidden\"][data-variant=\"up\"] {\n transform: translate3d(0, var(--tempest-reveal-distance, 1.5rem), 0);\n}\n\n.reveal[data-state=\"hidden\"][data-variant=\"down\"] {\n transform: translate3d(0, calc(-1 * var(--tempest-reveal-distance, 1.5rem)), 0);\n}\n\n.reveal[data-state=\"hidden\"][data-variant=\"left\"] {\n transform: translate3d(var(--tempest-reveal-distance, 1.5rem), 0, 0);\n}\n\n.reveal[data-state=\"hidden\"][data-variant=\"right\"] {\n transform: translate3d(calc(-1 * var(--tempest-reveal-distance, 1.5rem)), 0, 0);\n}\n\n.reveal[data-state=\"hidden\"][data-variant=\"scale\"] {\n transform: scale(var(--tempest-reveal-scale, 0.95));\n}\n\n.reveal[data-state=\"shown\"] {\n opacity: 1;\n transform: none;\n transition:\n opacity var(--tempest-reveal-duration, var(--tempest-duration-slower))\n var(--tempest-reveal-easing, var(--tempest-ease-out)),\n transform var(--tempest-reveal-duration, var(--tempest-duration-slower))\n var(--tempest-reveal-easing, var(--tempest-ease-emphasized));\n transition-delay: var(--tempest-reveal-delay, 0ms);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .reveal[data-state][data-variant] {\n opacity: 1;\n transform: none;\n transition: none;\n }\n}\n"],"mappings":";"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Reveal.module.js","names":[],"sources":["../../../src/components/Reveal/Reveal.module.css"],"sourcesContent":[".reveal[data-state=\"hidden\"] {\n opacity: 0;\n}\n\n.reveal[data-state=\"hidden\"][data-variant=\"up\"] {\n transform: translate3d(0, var(--tempest-reveal-distance, 1.5rem), 0);\n}\n\n.reveal[data-state=\"hidden\"][data-variant=\"down\"] {\n transform: translate3d(0, calc(-1 * var(--tempest-reveal-distance, 1.5rem)), 0);\n}\n\n.reveal[data-state=\"hidden\"][data-variant=\"left\"] {\n transform: translate3d(var(--tempest-reveal-distance, 1.5rem), 0, 0);\n}\n\n.reveal[data-state=\"hidden\"][data-variant=\"right\"] {\n transform: translate3d(calc(-1 * var(--tempest-reveal-distance, 1.5rem)), 0, 0);\n}\n\n.reveal[data-state=\"hidden\"][data-variant=\"scale\"] {\n transform: scale(var(--tempest-reveal-scale, 0.95));\n}\n\n.reveal[data-state=\"shown\"] {\n opacity: 1;\n transform: none;\n transition:\n opacity var(--tempest-reveal-duration, var(--tempest-duration-slower))\n var(--tempest-reveal-easing, var(--tempest-ease-out)),\n transform var(--tempest-reveal-duration, var(--tempest-duration-slower))\n var(--tempest-reveal-easing, var(--tempest-ease-emphasized));\n transition-delay: var(--tempest-reveal-delay, 0ms);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .reveal[data-state][data-variant] {\n opacity: 1;\n transform: none;\n transition: none;\n }\n}\n"],"mappings":";"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e=.001;function t(e){let t=e.rootBounds,n=e.boundingClientRect;return!t||n.width<=0||n.height<=0?1:Math.min(1,t.height/n.height)*Math.min(1,t.width/n.width)}function n(e,n){return n?e*t(n):e}exports.RATIO_EPSILON=e,exports.effectiveThreshold=n,exports.reachableRatio=t;
|
|
2
|
+
//# sourceMappingURL=reveal-threshold.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reveal-threshold.cjs","names":[],"sources":["../../../src/components/Reveal/reveal-threshold.ts"],"sourcesContent":["/**\n * Tolerance for comparing intersection ratios.\n *\n * Browsers report `intersectionRatio` as the quotient of two rounded areas, so a\n * box sitting exactly on its threshold can come back a hair below it. Without\n * the slack the observer fires (it crossed) and the comparison says it did not.\n */\nexport const RATIO_EPSILON = 0.001;\n\n/**\n * Highest `intersectionRatio` the target can ever reach inside the root.\n *\n * A box taller (or wider) than the root never fits in it: a section three\n * viewports tall tops out at a ratio of about 0.33. Any threshold above that is\n * unreachable, and an observer asked for it never reports the crossing.\n *\n * @param entry - An observation of the target; only its geometry is read.\n * @returns A value in `(0, 1]`, or `1` when the geometry is unknown (no\n * `rootBounds`, as in a cross-origin iframe, or an empty box).\n */\nexport function reachableRatio(entry: IntersectionObserverEntry): number {\n const root = entry.rootBounds;\n const box = entry.boundingClientRect;\n if (!root || box.width <= 0 || box.height <= 0) return 1;\n return Math.min(1, root.height / box.height) * Math.min(1, root.width / box.width);\n}\n\n/**\n * The threshold `Reveal` actually observes with, given the one it was asked for.\n *\n * The requested threshold is read as \"this fraction of whichever is smaller,\n * the element or the viewport\". For a box that fits, that is the plain ratio;\n * for a box taller than the viewport it scales the threshold by the reachable\n * ratio, so `threshold={0.5}` on a 3-viewport section reveals once it fills\n * half the viewport instead of never.\n *\n * @param threshold - The requested threshold, in `[0, 1]`.\n * @param entry - The latest observation, or `null` before the first one.\n * @returns The threshold to observe with.\n */\nexport function effectiveThreshold(\n threshold: number,\n entry: IntersectionObserverEntry | null,\n): number {\n if (!entry) return threshold;\n return threshold * reachableRatio(entry);\n}\n"],"mappings":"AAOA,IAAa,EAAgB,KAa7B,SAAgB,EAAe,EAA0C,CACrE,IAAM,EAAO,EAAM,WACb,EAAM,EAAM,mBAElB,MADI,CAAC,GAAQ,EAAI,OAAS,GAAK,EAAI,QAAU,EAAU,EAChD,KAAK,IAAI,EAAG,EAAK,OAAS,EAAI,MAAM,EAAI,KAAK,IAAI,EAAG,EAAK,MAAQ,EAAI,KAAK,CACrF,CAeA,SAAgB,EACZ,EACA,EACM,CAEN,OADK,EACE,EAAY,EAAe,CAAK,EADpB,CAEvB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/components/Reveal/reveal-threshold.ts
|
|
2
|
+
var e = .001;
|
|
3
|
+
function t(e) {
|
|
4
|
+
let t = e.rootBounds, n = e.boundingClientRect;
|
|
5
|
+
return !t || n.width <= 0 || n.height <= 0 ? 1 : Math.min(1, t.height / n.height) * Math.min(1, t.width / n.width);
|
|
6
|
+
}
|
|
7
|
+
function n(e, n) {
|
|
8
|
+
return n ? e * t(n) : e;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { e as RATIO_EPSILON, n as effectiveThreshold, t as reachableRatio };
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=reveal-threshold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reveal-threshold.js","names":[],"sources":["../../../src/components/Reveal/reveal-threshold.ts"],"sourcesContent":["/**\n * Tolerance for comparing intersection ratios.\n *\n * Browsers report `intersectionRatio` as the quotient of two rounded areas, so a\n * box sitting exactly on its threshold can come back a hair below it. Without\n * the slack the observer fires (it crossed) and the comparison says it did not.\n */\nexport const RATIO_EPSILON = 0.001;\n\n/**\n * Highest `intersectionRatio` the target can ever reach inside the root.\n *\n * A box taller (or wider) than the root never fits in it: a section three\n * viewports tall tops out at a ratio of about 0.33. Any threshold above that is\n * unreachable, and an observer asked for it never reports the crossing.\n *\n * @param entry - An observation of the target; only its geometry is read.\n * @returns A value in `(0, 1]`, or `1` when the geometry is unknown (no\n * `rootBounds`, as in a cross-origin iframe, or an empty box).\n */\nexport function reachableRatio(entry: IntersectionObserverEntry): number {\n const root = entry.rootBounds;\n const box = entry.boundingClientRect;\n if (!root || box.width <= 0 || box.height <= 0) return 1;\n return Math.min(1, root.height / box.height) * Math.min(1, root.width / box.width);\n}\n\n/**\n * The threshold `Reveal` actually observes with, given the one it was asked for.\n *\n * The requested threshold is read as \"this fraction of whichever is smaller,\n * the element or the viewport\". For a box that fits, that is the plain ratio;\n * for a box taller than the viewport it scales the threshold by the reachable\n * ratio, so `threshold={0.5}` on a 3-viewport section reveals once it fills\n * half the viewport instead of never.\n *\n * @param threshold - The requested threshold, in `[0, 1]`.\n * @param entry - The latest observation, or `null` before the first one.\n * @returns The threshold to observe with.\n */\nexport function effectiveThreshold(\n threshold: number,\n entry: IntersectionObserverEntry | null,\n): number {\n if (!entry) return threshold;\n return threshold * reachableRatio(entry);\n}\n"],"mappings":";AAOA,IAAa,IAAgB;AAa7B,SAAgB,EAAe,GAA0C;CACrE,IAAM,IAAO,EAAM,YACb,IAAM,EAAM;CAElB,OADI,CAAC,KAAQ,EAAI,SAAS,KAAK,EAAI,UAAU,IAAU,IAChD,KAAK,IAAI,GAAG,EAAK,SAAS,EAAI,MAAM,IAAI,KAAK,IAAI,GAAG,EAAK,QAAQ,EAAI,KAAK;AACrF;AAeA,SAAgB,EACZ,GACA,GACM;CAEN,OADK,IACE,IAAY,EAAe,CAAK,IADpB;AAEvB"}
|