@gunkin/uiify 0.0.11-alpha → 0.0.12-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/components/behavior.css +12 -0
  2. package/dist/components/behavior.css.map +1 -1
  3. package/dist/components/header/Header.d.ts +3 -19
  4. package/dist/components/header/Header.d.ts.map +1 -1
  5. package/dist/components/header/Header.js +4 -253
  6. package/dist/components/header/Header.js.map +1 -1
  7. package/dist/components/header/client/HeaderClient.d.ts +7 -0
  8. package/dist/components/header/client/HeaderClient.d.ts.map +1 -0
  9. package/dist/components/header/client/HeaderClient.js +93 -0
  10. package/dist/components/header/client/HeaderClient.js.map +1 -0
  11. package/dist/components/header/client/index.d.ts +3 -0
  12. package/dist/components/header/client/index.d.ts.map +1 -0
  13. package/dist/components/header/client/index.js +6 -0
  14. package/dist/components/header/client/index.js.map +1 -0
  15. package/dist/components/header/client.d.ts +1 -0
  16. package/dist/components/header/client.js +1 -0
  17. package/dist/components/header/index.d.ts +2 -3
  18. package/dist/components/header/index.d.ts.map +1 -1
  19. package/dist/components/header/index.js +2 -15
  20. package/dist/components/header/index.js.map +1 -1
  21. package/dist/components/header/types.d.ts +7 -63
  22. package/dist/components/header/types.d.ts.map +1 -1
  23. package/package.json +1 -1
  24. package/dist/components/header/use-header-scroll-state.d.ts +0 -4
  25. package/dist/components/header/use-header-scroll-state.d.ts.map +0 -1
  26. package/dist/components/header/use-header-scroll-state.js +0 -83
  27. package/dist/components/header/use-header-scroll-state.js.map +0 -1
  28. package/dist/components/header/use-header.d.ts +0 -4
  29. package/dist/components/header/use-header.d.ts.map +0 -1
  30. package/dist/components/header/use-header.js +0 -80
  31. package/dist/components/header/use-header.js.map +0 -1
@@ -1,5 +1,17 @@
1
1
  @layer ui.reset, ui.behavior, ui.tokens, ui.theme, app;
2
2
  @layer ui.behavior {
3
+ [data-uiify-header][data-placement=sticky] {
4
+ position: sticky;
5
+ inset-block-start: 0;
6
+ }
7
+ [data-uiify-header][data-placement=sticky][data-state=hidden]:not(:focus-within, :has(dialog[open], details[open], :popover-open)) {
8
+ translate: 0 -100%;
9
+ }
10
+ @media (prefers-reduced-motion: no-preference) {
11
+ [data-uiify-header][data-placement=sticky][data-state] {
12
+ transition: translate 200ms ease-out;
13
+ }
14
+ }
3
15
  [popover]:not(:popover-open) {
4
16
  display: none;
5
17
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/behavior.css"],"sourcesContent":["/* Behavioral rules for @gunkin/uiify/components — zero visual opinion.\n * Import is required: @import \"@gunkin/uiify/components/behavior.css\";\n * Cascade order: consumer app layer wins without specificity fights. */\n@layer ui.reset, ui.behavior, ui.tokens, ui.theme, app;\n\n@layer ui.behavior {\n [popover]:not(:popover-open) {\n display: none;\n }\n\n /* Native modal dialogs: wheel/touch scrolling inside the dialog must not chain to the page behind it. */\n dialog:modal {\n overscroll-behavior: contain;\n }\n\n /* Open modal dialogs lock the page scroll, iOS Safari included (checked on iOS 27: a swipe on\n the backdrop or the dialog leaves scrollY unchanged). The stable gutter keeps a classic\n scrollbar's width, so the page does not shift when the dialog opens. */\n :root:has(dialog:modal) {\n overflow: hidden;\n scrollbar-gutter: stable;\n }\n\n /* Closed dialogs stay hidden even when author CSS sets display. */\n dialog:not([open]) {\n display: none;\n }\n\n [data-anchor]:not([data-positioning]) {\n anchor-name: var(--uiify-anchor, attr(data-anchor type(<custom-ident>)));\n }\n\n [data-positioning=\"native\"] {\n position: fixed;\n inset: auto;\n margin: 0;\n position-try-fallbacks: flip-block, flip-inline;\n }\n\n [data-positioning=\"native\"][data-anchor] {\n position-anchor: var(--uiify-anchor, attr(data-anchor type(<custom-ident>)));\n }\n\n [data-positioning=\"native\"][data-side=\"top\"] {\n position-area: top;\n margin-block-end: var(--uiify-anchor-offset, 0);\n }\n\n [data-positioning=\"native\"][data-side=\"right\"] {\n position-area: right;\n margin-inline-start: var(--uiify-anchor-offset, 0);\n }\n\n [data-positioning=\"native\"][data-side=\"bottom\"] {\n position-area: bottom;\n margin-block-start: var(--uiify-anchor-offset, 0);\n }\n\n [data-positioning=\"native\"][data-side=\"left\"] {\n position-area: left;\n margin-inline-end: var(--uiify-anchor-offset, 0);\n }\n\n [data-positioning=\"native\"][data-side=\"top\"][data-align=\"start\"] {\n position-area: top span-right;\n justify-self: start;\n }\n\n [data-positioning=\"native\"][data-side=\"top\"][data-align=\"end\"] {\n position-area: top span-left;\n justify-self: end;\n }\n\n [data-positioning=\"native\"][data-side=\"bottom\"][data-align=\"start\"] {\n position-area: bottom span-right;\n justify-self: start;\n }\n\n [data-positioning=\"native\"][data-side=\"bottom\"][data-align=\"end\"] {\n position-area: bottom span-left;\n justify-self: end;\n }\n\n [data-positioning=\"native\"][data-side=\"right\"][data-align=\"start\"] {\n align-self: start;\n position-area: right span-bottom;\n }\n\n [data-positioning=\"native\"][data-side=\"right\"][data-align=\"end\"] {\n align-self: end;\n position-area: right span-top;\n }\n\n [data-positioning=\"native\"][data-side=\"left\"][data-align=\"start\"] {\n align-self: start;\n position-area: left span-bottom;\n }\n\n [data-positioning=\"native\"][data-side=\"left\"][data-align=\"end\"] {\n align-self: end;\n position-area: left span-top;\n }\n\n /*\n * Local open-state hooks. Top layer does not change DOM ancestry, so a scope\n * that directly contains its surface can read the native state. Consumers\n * style with the selector or with the variable; neither is a second source of truth.\n *\n * Compound roots and their public trigger parts share one component identity plus\n * `data-part`, so native state stays readable without a second scope convention.\n */\n [data-uiify-modal][data-part=\"root\"]:has(> [data-uiify-modal][data-part=\"content\"][open])\n > [data-uiify-modal][data-part=\"trigger\"],\n [data-uiify-alert-modal][data-part=\"root\"]:has(\n > [data-uiify-alert-modal][data-part=\"content\"][open]\n )\n > [data-uiify-alert-modal][data-part=\"trigger\"],\n [data-uiify-popup][data-part=\"root\"]:has(> [data-uiify-popup][data-part=\"content\"]:popover-open)\n > [data-uiify-popup][data-part=\"trigger\"] {\n --uiify-trigger-open: 1;\n }\n\n [data-uiify-accordion] > [data-part=\"item\"][data-disabled] > summary,\n [data-uiify-collapsible][data-disabled] > summary {\n cursor: not-allowed;\n pointer-events: none;\n }\n\n /* Customizable select: opts the control and its picker into the browser's\n base styles so the picker becomes a styleable, top-layer popover with\n implicit anchor positioning. Behavior only — no visual opinion. Engines\n without support ignore this and keep the classic OS picker, which stays\n fully functional. */\n [data-uiify-select],\n [data-uiify-select]::picker(select) {\n appearance: base-select;\n }\n\n [data-uiify-tabs] > [data-part=\"item\"] > [data-part=\"control\"] {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n /* stylelint-disable-next-line property-no-deprecated -- kept for older browser support alongside clip-path */\n clip: rect(0, 0, 0, 0);\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n }\n\n [data-uiify-tabs] > [data-part=\"item\"] > [data-part=\"panel\"] {\n display: none;\n }\n\n [data-uiify-tabs] > [data-part=\"item\"] > [data-part=\"control\"]:checked ~ [data-part=\"panel\"] {\n display: block;\n }\n\n [data-uiify-stepper] > [data-part=\"step\"] > [data-part=\"panel\"] {\n display: none;\n }\n\n [data-uiify-stepper] > [data-part=\"step\"] > [data-part=\"control\"]:checked ~ [data-part=\"panel\"] {\n display: block;\n }\n\n [data-uiify-tabs] [data-part=\"trigger\"][data-disabled] {\n cursor: not-allowed;\n pointer-events: none;\n }\n\n [data-uiify-spinner][data-state=\"delayed\"] {\n animation-name: uiify-spinner-show;\n animation-duration: 0s;\n animation-delay: attr(data-delay type(<time>), 0s);\n animation-fill-mode: forwards;\n visibility: hidden;\n }\n\n @keyframes uiify-spinner-show {\n to {\n visibility: visible;\n }\n }\n\n [data-uiify-breadcrumb] [data-part=\"ellipsis\"] > ol {\n list-style: none;\n margin: 0;\n padding: 0;\n }\n\n [data-uiify-carousel] > [data-part=\"viewport\"] {\n display: grid;\n min-inline-size: 0;\n min-block-size: 0;\n gap: var(--uiify-carousel-gap, 0);\n scroll-behavior: auto;\n }\n\n [data-uiify-carousel][data-axis=\"inline\"] > [data-part=\"viewport\"] {\n grid-auto-flow: column;\n grid-auto-columns: var(--uiify-carousel-slide-size, 100%);\n overflow-inline: auto;\n overflow-block: hidden;\n scroll-snap-type: inline mandatory;\n }\n\n [data-uiify-carousel][data-axis=\"block\"] > [data-part=\"viewport\"] {\n grid-auto-flow: row;\n grid-auto-rows: var(--uiify-carousel-slide-size, 100%);\n overflow-block: auto;\n overflow-inline: hidden;\n scroll-snap-type: block mandatory;\n }\n\n [data-uiify-carousel] > [data-part=\"viewport\"] > [data-part=\"slide\"] {\n min-inline-size: 0;\n min-block-size: 0;\n scroll-snap-align: start;\n }\n\n [data-uiify-carousel] > [data-part=\"viewport\"]:focus-visible,\n [data-uiify-carousel] > button[data-part=\"controls\"]:focus-visible,\n [data-uiify-carousel] > [data-part=\"dots\"] > a:focus-visible {\n outline: auto;\n }\n\n @media (prefers-reduced-motion: no-preference) {\n [data-uiify-carousel] > [data-part=\"viewport\"] {\n scroll-behavior: smooth;\n }\n }\n\n [data-uiify-carousel] > [data-part=\"viewport\"][data-dragging] {\n scroll-behavior: auto;\n scroll-snap-type: none;\n }\n\n [data-uiify-carousel][data-mode=\"fade\"][data-enhanced] > [data-part=\"viewport\"] {\n grid-auto-flow: row;\n grid-template-columns: 100%;\n grid-auto-columns: auto;\n overflow: hidden;\n scroll-snap-type: none;\n touch-action: pan-y pinch-zoom;\n }\n\n [data-uiify-carousel][data-mode=\"fade\"][data-enhanced]\n > [data-part=\"viewport\"]\n > [data-part=\"slide\"] {\n grid-area: 1 / 1;\n opacity: 0;\n pointer-events: none;\n }\n\n [data-uiify-carousel][data-mode=\"fade\"][data-enhanced]\n > [data-part=\"viewport\"]\n > [data-part=\"slide\"][data-state=\"active\"] {\n opacity: 1;\n pointer-events: auto;\n }\n\n @media (prefers-reduced-motion: no-preference) {\n [data-uiify-carousel][data-mode=\"fade\"][data-enhanced]\n > [data-part=\"viewport\"]\n > [data-part=\"slide\"] {\n transition: opacity var(--uiify-carousel-fade-duration, 300ms) ease;\n }\n }\n\n [data-uiify-virtual-scroll] {\n --uiify-virtual-scroll-row-height: 64px;\n\n overflow-y: auto;\n }\n\n [data-uiify-virtual-scroll] > [data-part=\"spacer\"] {\n position: relative;\n block-size: var(\n --uiify-virtual-scroll-total-size,\n calc(var(--uiify-virtual-scroll-count, 0) * var(--uiify-virtual-scroll-row-height))\n );\n }\n\n [data-uiify-virtual-scroll] [data-part=\"row\"] {\n --uiify-row-position: var(\n --uiify-row-offset,\n calc(\n (var(--uiify-range-start, 0) + var(--uiify-slot-index, 0)) *\n var(--uiify-virtual-scroll-row-height)\n )\n );\n\n position: absolute;\n inset-inline: 0;\n block-size: var(--uiify-row-height, var(--uiify-virtual-scroll-row-height));\n translate: 0 var(--uiify-row-position);\n }\n\n /* Horizontal: the row size runs along the inline axis. Rows sit at a logical\n inline offset so RTL needs no direction selector; child combinators keep a\n vertical list nested inside a horizontal row on the vertical rules. */\n [data-uiify-virtual-scroll][data-orientation=\"horizontal\"] {\n overflow: auto hidden;\n }\n\n [data-uiify-virtual-scroll][data-orientation=\"horizontal\"] > [data-part=\"spacer\"] {\n block-size: 100%;\n inline-size: var(\n --uiify-virtual-scroll-total-size,\n calc(var(--uiify-virtual-scroll-count, 0) * var(--uiify-virtual-scroll-row-height))\n );\n }\n\n [data-uiify-virtual-scroll][data-orientation=\"horizontal\"]\n > [data-part=\"spacer\"]\n > [data-part=\"row\"] {\n inset-block: 0;\n inset-inline: var(--uiify-row-position) auto;\n block-size: auto;\n inline-size: var(--uiify-row-height, var(--uiify-virtual-scroll-row-height));\n translate: none;\n }\n\n /*\n * Toast list changes commit as React view transitions typed \"uiify-toast\".\n * Only the toast cards are captured: the page root is not snapshotted and\n * stays clickable while they move.\n */\n :root:active-view-transition-type(uiify-toast) {\n view-transition-name: none;\n }\n\n :root:active-view-transition-type(uiify-toast)::view-transition {\n pointer-events: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n ::view-transition-group(.uiify-toast),\n ::view-transition-old(.uiify-toast),\n ::view-transition-new(.uiify-toast) {\n animation: none;\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/behavior.css"],"sourcesContent":["/* Behavioral rules for @gunkin/uiify/components — zero visual opinion.\n * Import is required: @import \"@gunkin/uiify/components/behavior.css\";\n * Cascade order: consumer app layer wins without specificity fights. */\n@layer ui.reset, ui.behavior, ui.tokens, ui.theme, app;\n\n@layer ui.behavior {\n [data-uiify-header][data-placement=\"sticky\"] {\n position: sticky;\n inset-block-start: 0;\n }\n\n [data-uiify-header][data-placement=\"sticky\"][data-state=\"hidden\"]:not(\n :focus-within,\n :has(dialog[open], details[open], :popover-open)\n ) {\n translate: 0 -100%;\n }\n\n @media (prefers-reduced-motion: no-preference) {\n [data-uiify-header][data-placement=\"sticky\"][data-state] {\n transition: translate 200ms ease-out;\n }\n }\n\n [popover]:not(:popover-open) {\n display: none;\n }\n\n /* Native modal dialogs: wheel/touch scrolling inside the dialog must not chain to the page behind it. */\n dialog:modal {\n overscroll-behavior: contain;\n }\n\n /* Open modal dialogs lock the page scroll, iOS Safari included (checked on iOS 27: a swipe on\n the backdrop or the dialog leaves scrollY unchanged). The stable gutter keeps a classic\n scrollbar's width, so the page does not shift when the dialog opens. */\n :root:has(dialog:modal) {\n overflow: hidden;\n scrollbar-gutter: stable;\n }\n\n /* Closed dialogs stay hidden even when author CSS sets display. */\n dialog:not([open]) {\n display: none;\n }\n\n [data-anchor]:not([data-positioning]) {\n anchor-name: var(--uiify-anchor, attr(data-anchor type(<custom-ident>)));\n }\n\n [data-positioning=\"native\"] {\n position: fixed;\n inset: auto;\n margin: 0;\n position-try-fallbacks: flip-block, flip-inline;\n }\n\n [data-positioning=\"native\"][data-anchor] {\n position-anchor: var(--uiify-anchor, attr(data-anchor type(<custom-ident>)));\n }\n\n [data-positioning=\"native\"][data-side=\"top\"] {\n position-area: top;\n margin-block-end: var(--uiify-anchor-offset, 0);\n }\n\n [data-positioning=\"native\"][data-side=\"right\"] {\n position-area: right;\n margin-inline-start: var(--uiify-anchor-offset, 0);\n }\n\n [data-positioning=\"native\"][data-side=\"bottom\"] {\n position-area: bottom;\n margin-block-start: var(--uiify-anchor-offset, 0);\n }\n\n [data-positioning=\"native\"][data-side=\"left\"] {\n position-area: left;\n margin-inline-end: var(--uiify-anchor-offset, 0);\n }\n\n [data-positioning=\"native\"][data-side=\"top\"][data-align=\"start\"] {\n position-area: top span-right;\n justify-self: start;\n }\n\n [data-positioning=\"native\"][data-side=\"top\"][data-align=\"end\"] {\n position-area: top span-left;\n justify-self: end;\n }\n\n [data-positioning=\"native\"][data-side=\"bottom\"][data-align=\"start\"] {\n position-area: bottom span-right;\n justify-self: start;\n }\n\n [data-positioning=\"native\"][data-side=\"bottom\"][data-align=\"end\"] {\n position-area: bottom span-left;\n justify-self: end;\n }\n\n [data-positioning=\"native\"][data-side=\"right\"][data-align=\"start\"] {\n align-self: start;\n position-area: right span-bottom;\n }\n\n [data-positioning=\"native\"][data-side=\"right\"][data-align=\"end\"] {\n align-self: end;\n position-area: right span-top;\n }\n\n [data-positioning=\"native\"][data-side=\"left\"][data-align=\"start\"] {\n align-self: start;\n position-area: left span-bottom;\n }\n\n [data-positioning=\"native\"][data-side=\"left\"][data-align=\"end\"] {\n align-self: end;\n position-area: left span-top;\n }\n\n /*\n * Local open-state hooks. Top layer does not change DOM ancestry, so a scope\n * that directly contains its surface can read the native state. Consumers\n * style with the selector or with the variable; neither is a second source of truth.\n *\n * Compound roots and their public trigger parts share one component identity plus\n * `data-part`, so native state stays readable without a second scope convention.\n */\n [data-uiify-modal][data-part=\"root\"]:has(> [data-uiify-modal][data-part=\"content\"][open])\n > [data-uiify-modal][data-part=\"trigger\"],\n [data-uiify-alert-modal][data-part=\"root\"]:has(\n > [data-uiify-alert-modal][data-part=\"content\"][open]\n )\n > [data-uiify-alert-modal][data-part=\"trigger\"],\n [data-uiify-popup][data-part=\"root\"]:has(> [data-uiify-popup][data-part=\"content\"]:popover-open)\n > [data-uiify-popup][data-part=\"trigger\"] {\n --uiify-trigger-open: 1;\n }\n\n [data-uiify-accordion] > [data-part=\"item\"][data-disabled] > summary,\n [data-uiify-collapsible][data-disabled] > summary {\n cursor: not-allowed;\n pointer-events: none;\n }\n\n /* Customizable select: opts the control and its picker into the browser's\n base styles so the picker becomes a styleable, top-layer popover with\n implicit anchor positioning. Behavior only — no visual opinion. Engines\n without support ignore this and keep the classic OS picker, which stays\n fully functional. */\n [data-uiify-select],\n [data-uiify-select]::picker(select) {\n appearance: base-select;\n }\n\n [data-uiify-tabs] > [data-part=\"item\"] > [data-part=\"control\"] {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n /* stylelint-disable-next-line property-no-deprecated -- kept for older browser support alongside clip-path */\n clip: rect(0, 0, 0, 0);\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n }\n\n [data-uiify-tabs] > [data-part=\"item\"] > [data-part=\"panel\"] {\n display: none;\n }\n\n [data-uiify-tabs] > [data-part=\"item\"] > [data-part=\"control\"]:checked ~ [data-part=\"panel\"] {\n display: block;\n }\n\n [data-uiify-stepper] > [data-part=\"step\"] > [data-part=\"panel\"] {\n display: none;\n }\n\n [data-uiify-stepper] > [data-part=\"step\"] > [data-part=\"control\"]:checked ~ [data-part=\"panel\"] {\n display: block;\n }\n\n [data-uiify-tabs] [data-part=\"trigger\"][data-disabled] {\n cursor: not-allowed;\n pointer-events: none;\n }\n\n [data-uiify-spinner][data-state=\"delayed\"] {\n animation-name: uiify-spinner-show;\n animation-duration: 0s;\n animation-delay: attr(data-delay type(<time>), 0s);\n animation-fill-mode: forwards;\n visibility: hidden;\n }\n\n @keyframes uiify-spinner-show {\n to {\n visibility: visible;\n }\n }\n\n [data-uiify-breadcrumb] [data-part=\"ellipsis\"] > ol {\n list-style: none;\n margin: 0;\n padding: 0;\n }\n\n [data-uiify-carousel] > [data-part=\"viewport\"] {\n display: grid;\n min-inline-size: 0;\n min-block-size: 0;\n gap: var(--uiify-carousel-gap, 0);\n scroll-behavior: auto;\n }\n\n [data-uiify-carousel][data-axis=\"inline\"] > [data-part=\"viewport\"] {\n grid-auto-flow: column;\n grid-auto-columns: var(--uiify-carousel-slide-size, 100%);\n overflow-inline: auto;\n overflow-block: hidden;\n scroll-snap-type: inline mandatory;\n }\n\n [data-uiify-carousel][data-axis=\"block\"] > [data-part=\"viewport\"] {\n grid-auto-flow: row;\n grid-auto-rows: var(--uiify-carousel-slide-size, 100%);\n overflow-block: auto;\n overflow-inline: hidden;\n scroll-snap-type: block mandatory;\n }\n\n [data-uiify-carousel] > [data-part=\"viewport\"] > [data-part=\"slide\"] {\n min-inline-size: 0;\n min-block-size: 0;\n scroll-snap-align: start;\n }\n\n [data-uiify-carousel] > [data-part=\"viewport\"]:focus-visible,\n [data-uiify-carousel] > button[data-part=\"controls\"]:focus-visible,\n [data-uiify-carousel] > [data-part=\"dots\"] > a:focus-visible {\n outline: auto;\n }\n\n @media (prefers-reduced-motion: no-preference) {\n [data-uiify-carousel] > [data-part=\"viewport\"] {\n scroll-behavior: smooth;\n }\n }\n\n [data-uiify-carousel] > [data-part=\"viewport\"][data-dragging] {\n scroll-behavior: auto;\n scroll-snap-type: none;\n }\n\n [data-uiify-carousel][data-mode=\"fade\"][data-enhanced] > [data-part=\"viewport\"] {\n grid-auto-flow: row;\n grid-template-columns: 100%;\n grid-auto-columns: auto;\n overflow: hidden;\n scroll-snap-type: none;\n touch-action: pan-y pinch-zoom;\n }\n\n [data-uiify-carousel][data-mode=\"fade\"][data-enhanced]\n > [data-part=\"viewport\"]\n > [data-part=\"slide\"] {\n grid-area: 1 / 1;\n opacity: 0;\n pointer-events: none;\n }\n\n [data-uiify-carousel][data-mode=\"fade\"][data-enhanced]\n > [data-part=\"viewport\"]\n > [data-part=\"slide\"][data-state=\"active\"] {\n opacity: 1;\n pointer-events: auto;\n }\n\n @media (prefers-reduced-motion: no-preference) {\n [data-uiify-carousel][data-mode=\"fade\"][data-enhanced]\n > [data-part=\"viewport\"]\n > [data-part=\"slide\"] {\n transition: opacity var(--uiify-carousel-fade-duration, 300ms) ease;\n }\n }\n\n [data-uiify-virtual-scroll] {\n --uiify-virtual-scroll-row-height: 64px;\n\n overflow-y: auto;\n }\n\n [data-uiify-virtual-scroll] > [data-part=\"spacer\"] {\n position: relative;\n block-size: var(\n --uiify-virtual-scroll-total-size,\n calc(var(--uiify-virtual-scroll-count, 0) * var(--uiify-virtual-scroll-row-height))\n );\n }\n\n [data-uiify-virtual-scroll] [data-part=\"row\"] {\n --uiify-row-position: var(\n --uiify-row-offset,\n calc(\n (var(--uiify-range-start, 0) + var(--uiify-slot-index, 0)) *\n var(--uiify-virtual-scroll-row-height)\n )\n );\n\n position: absolute;\n inset-inline: 0;\n block-size: var(--uiify-row-height, var(--uiify-virtual-scroll-row-height));\n translate: 0 var(--uiify-row-position);\n }\n\n /* Horizontal: the row size runs along the inline axis. Rows sit at a logical\n inline offset so RTL needs no direction selector; child combinators keep a\n vertical list nested inside a horizontal row on the vertical rules. */\n [data-uiify-virtual-scroll][data-orientation=\"horizontal\"] {\n overflow: auto hidden;\n }\n\n [data-uiify-virtual-scroll][data-orientation=\"horizontal\"] > [data-part=\"spacer\"] {\n block-size: 100%;\n inline-size: var(\n --uiify-virtual-scroll-total-size,\n calc(var(--uiify-virtual-scroll-count, 0) * var(--uiify-virtual-scroll-row-height))\n );\n }\n\n [data-uiify-virtual-scroll][data-orientation=\"horizontal\"]\n > [data-part=\"spacer\"]\n > [data-part=\"row\"] {\n inset-block: 0;\n inset-inline: var(--uiify-row-position) auto;\n block-size: auto;\n inline-size: var(--uiify-row-height, var(--uiify-virtual-scroll-row-height));\n translate: none;\n }\n\n /*\n * Toast list changes commit as React view transitions typed \"uiify-toast\".\n * Only the toast cards are captured: the page root is not snapshotted and\n * stays clickable while they move.\n */\n :root:active-view-transition-type(uiify-toast) {\n view-transition-name: none;\n }\n\n :root:active-view-transition-type(uiify-toast)::view-transition {\n pointer-events: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n ::view-transition-group(.uiify-toast),\n ::view-transition-old(.uiify-toast),\n ::view-transition-new(.uiify-toast) {\n animation: none;\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,26 +1,10 @@
1
- import { type ReactElement } from "react";
2
- import { useHeader } from "./use-header.js";
3
- import { useHeaderScrollState } from "./use-header-scroll-state.js";
4
- import type { HeaderRootProps, HeaderToggleProps, HeaderMobileNavProps, HeaderCloseProps } from "./types.js";
5
- export type { HeaderBehavior, HeaderCloseProps, HeaderMobileNavProps, HeaderMobileMode, HeaderPlacement, HeaderRootProps, HeaderToggleProps, UseHeaderOptions, UseHeaderReturn, UseHeaderScrollStateOptions, UseHeaderScrollStateReturn, } from "./types.js";
6
- export declare function HeaderRoot(props: HeaderRootProps): ReactElement | null;
1
+ import type { ReactElement } from "react";
2
+ import type { HeaderRootProps } from "./types.js";
3
+ export declare function HeaderRoot({ placement, ...props }: HeaderRootProps): ReactElement;
7
4
  export declare namespace HeaderRoot {
8
5
  var displayName: string;
9
6
  }
10
- export declare function HeaderToggle(props: HeaderToggleProps): ReactElement | null;
11
- export declare function HeaderMobileNav(props: HeaderMobileNavProps): ReactElement | null;
12
- export declare namespace HeaderMobileNav {
13
- var displayName: string;
14
- }
15
- export declare function HeaderClose(props: HeaderCloseProps): ReactElement | null;
16
- export declare namespace HeaderClose {
17
- var displayName: string;
18
- }
19
7
  export declare const Header: {
20
- Close: typeof HeaderClose;
21
- MobileNav: typeof HeaderMobileNav;
22
8
  Root: typeof HeaderRoot;
23
- Toggle: typeof HeaderToggle;
24
9
  };
25
- export { useHeader, useHeaderScrollState };
26
10
  //# sourceMappingURL=Header.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../../src/components/header/Header.tsx"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,YAAY,EAElB,MAAM,OAAO,CAAC;AAMf,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAEV,eAAe,EAEf,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,YAAY,CAAC;AAsCpB,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,YAAY,GAAG,IAAI,CA2FtE;yBA3Fe,UAAU;;;AA8F1B,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,YAAY,GAAG,IAAI,CA+B1E;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,YAAY,GAAG,IAAI,CAkEhF;yBAlEe,eAAe;;;AAqE/B,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,YAAY,GAAG,IAAI,CAkCxE;yBAlCe,WAAW;;;AAqC3B,eAAO,MAAM,MAAM;;;;;CAKlB,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,CAAC"}
1
+ {"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../../src/components/header/Header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,wBAAgB,UAAU,CAAC,EAAE,SAAoB,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,GAAG,YAAY,CAE5F;yBAFe,UAAU;;;AAK1B,eAAO,MAAM,MAAM;;CAAuB,CAAC"}
@@ -1,260 +1,11 @@
1
- "use client";
2
1
  import { jsx } from "react/jsx-runtime";
3
- import {
4
- useCallback,
5
- useMemo,
6
- useRef
7
- } from "react";
8
- import { useIsomorphicLayoutEffect, useMergedRefs } from "@gunkin/uiify/hooks";
9
- import { createPartContext } from "@gunkin/uiify/core";
10
- import { useRenderElement } from "@gunkin/uiify/core/render";
11
- import { Drawer } from "../drawer/Drawer.js";
12
- import { useHeader } from "./use-header.js";
13
- import { useHeaderScrollState } from "./use-header-scroll-state.js";
14
- const [HeaderProvider, useHeaderContext] = createPartContext("Header");
15
- function isDrawerMode(mobileMode) {
16
- return mobileMode === "drawer" || mobileMode === "sheet" || mobileMode === "fullscreen";
17
- }
18
- function drawerSide(mobileMode) {
19
- if (mobileMode === "sheet") return "bottom";
20
- return "left";
21
- }
22
- function defaultModal(mobileMode) {
23
- return isDrawerMode(mobileMode);
24
- }
25
- function defaultLockScroll(mobileMode, modal) {
26
- return isDrawerMode(mobileMode) && modal;
27
- }
28
- function defaultCloseOnSelect(mobileMode) {
29
- return mobileMode !== "none";
30
- }
31
- function handleCloseOnSelect(event, closeOnSelect, close) {
32
- if (!closeOnSelect) return;
33
- const target = event.target;
34
- if (!(target instanceof Element)) return;
35
- const activator = target.closest("a[href], button:not([disabled])");
36
- if (!activator || !event.currentTarget.contains(activator)) return;
37
- close();
38
- }
39
- function HeaderRoot(props) {
40
- const {
41
- behavior = "none",
42
- children,
43
- closeOnSelect: closeOnSelectProp,
44
- defaultOpen,
45
- hidden: hiddenProp,
46
- lockScroll: lockScrollProp,
47
- mobileMode = "none",
48
- modal: modalProp,
49
- onOpenChange,
50
- open,
51
- placement = "static",
52
- scrolled: scrolledProp,
53
- ...consumerProps
54
- } = props;
55
- const modal = modalProp ?? defaultModal(mobileMode);
56
- const lockScroll = lockScrollProp ?? defaultLockScroll(mobileMode, modal);
57
- const closeOnSelect = closeOnSelectProp ?? defaultCloseOnSelect(mobileMode);
58
- const toggleRef = useRef(null);
59
- const wasOpenRef = useRef(false);
60
- const header = useHeader({
61
- closeOnSelect,
62
- mobileMode,
63
- ...defaultOpen !== void 0 ? { defaultOpen } : {},
64
- ...onOpenChange ? { onOpenChange } : {},
65
- ...open !== void 0 ? { open } : {}
66
- });
67
- useIsomorphicLayoutEffect(() => {
68
- if (wasOpenRef.current && !header.open && isDrawerMode(mobileMode)) {
69
- queueMicrotask(() => toggleRef.current?.focus({ preventScroll: true }));
70
- }
71
- wasOpenRef.current = header.open;
72
- }, [header.open, mobileMode]);
73
- const contextValue = useMemo(
74
- () => ({
75
- ...header,
76
- behavior,
77
- hidden: hiddenProp ?? false,
78
- lockScroll,
79
- modal,
80
- placement,
81
- scrolled: scrolledProp ?? false,
82
- toggleRef
83
- }),
84
- [behavior, header, hiddenProp, lockScroll, modal, placement, scrolledProp]
85
- );
86
- const rootElement = useRenderElement({
87
- defaultTag: "div",
88
- props: {
89
- ...consumerProps,
90
- "data-behavior": behavior,
91
- "data-hidden": hiddenProp ? "" : void 0,
92
- "data-lock-scroll": lockScroll && header.open && isDrawerMode(mobileMode) ? "" : void 0,
93
- "data-mobile-mode": mobileMode,
94
- "data-state": header.open ? "open" : "closed",
95
- "data-placement": placement,
96
- "data-scrolled": scrolledProp ? "" : void 0,
97
- children
98
- },
99
- state: {
100
- open: header.open,
101
- placement,
102
- behavior,
103
- mobileMode,
104
- scrolled: scrolledProp ?? false,
105
- hidden: hiddenProp ?? false
106
- }
107
- });
108
- const tree = /* @__PURE__ */ jsx(HeaderProvider, { value: contextValue, children: rootElement });
109
- if (isDrawerMode(mobileMode)) {
110
- return /* @__PURE__ */ jsx(
111
- Drawer.Root,
112
- {
113
- modal,
114
- onOpenChange: header.setOpen,
115
- open: header.open,
116
- side: drawerSide(mobileMode),
117
- children: tree
118
- }
119
- );
120
- }
121
- return tree;
2
+ function HeaderRoot({ placement = "static", ...props }) {
3
+ return /* @__PURE__ */ jsx("header", { ...props, "data-uiify-header": "", "data-placement": placement });
122
4
  }
123
5
  HeaderRoot.displayName = "HeaderRoot";
124
- function HeaderToggle(props) {
125
- const {
126
- closeLabel = "Close navigation",
127
- openLabel = "Open navigation",
128
- ref,
129
- onClick,
130
- ...consumerProps
131
- } = props;
132
- const { getToggleProps, mobileMode, open, toggle, toggleRef } = useHeaderContext("Toggle");
133
- const mergedRef = useMergedRefs(toggleRef, ref);
134
- const dialogMode = isDrawerMode(mobileMode);
135
- const toggleProps = getToggleProps({
136
- type: "button",
137
- "aria-haspopup": dialogMode ? "dialog" : void 0,
138
- "aria-label": open ? closeLabel : openLabel,
139
- onClick(event) {
140
- toggle();
141
- onClick?.(event);
142
- }
143
- });
144
- return useRenderElement({
145
- defaultTag: "button",
146
- props: {
147
- ...consumerProps,
148
- ref: mergedRef,
149
- ...toggleProps
150
- },
151
- state: { open }
152
- });
153
- }
154
- function HeaderMobileNav(props) {
155
- const { children, forceMount, onClick: consumerOnClick, ...consumerProps } = props;
156
- const { close, closeOnSelect, getMobileNavProps, mobileMode, open } = useHeaderContext("MobileNav");
157
- const onClick = useCallback(
158
- (event) => {
159
- handleCloseOnSelect(event, closeOnSelect, close);
160
- consumerOnClick?.(event);
161
- },
162
- [close, closeOnSelect, consumerOnClick]
163
- );
164
- const noneNav = useRenderElement({
165
- defaultTag: "nav",
166
- props: {
167
- ...consumerProps,
168
- ...getMobileNavProps({ onClick }),
169
- children
170
- },
171
- state: { open }
172
- });
173
- const drawerNav = useRenderElement({
174
- defaultTag: "nav",
175
- props: {
176
- ...consumerProps,
177
- ...getMobileNavProps({
178
- "data-mobile-mode": mobileMode,
179
- "data-state": open ? "open" : "closed",
180
- onClick
181
- }),
182
- children
183
- },
184
- state: { open, mobileMode }
185
- });
186
- const collapseNav = useRenderElement({
187
- defaultTag: "nav",
188
- props: {
189
- ...consumerProps,
190
- ...getMobileNavProps({
191
- "aria-hidden": open ? void 0 : true,
192
- "data-mobile-mode": mobileMode,
193
- "data-state": open ? "open" : "closed",
194
- hidden: open ? void 0 : true,
195
- onClick
196
- }),
197
- children
198
- },
199
- state: { open, mobileMode }
200
- });
201
- if (mobileMode === "none") {
202
- return noneNav;
203
- }
204
- if (mobileMode === "collapse") {
205
- if (!open && !forceMount) {
206
- return null;
207
- }
208
- return collapseNav;
209
- }
210
- return /* @__PURE__ */ jsx(Drawer.Content, { children: drawerNav });
211
- }
212
- HeaderMobileNav.displayName = "HeaderMobileNav";
213
- function HeaderClose(props) {
214
- const { children, className, onClick, ...consumerProps } = props;
215
- const { close, mobileMode } = useHeaderContext("Close");
216
- const handleClick = (event) => {
217
- close();
218
- onClick?.(event);
219
- };
220
- const closeButton = useRenderElement({
221
- defaultTag: "button",
222
- props: {
223
- ...consumerProps,
224
- type: "button",
225
- onClick: handleClick,
226
- ...className !== void 0 ? { className } : {},
227
- children
228
- },
229
- state: {}
230
- });
231
- if (isDrawerMode(mobileMode)) {
232
- return /* @__PURE__ */ jsx(
233
- Drawer.Close,
234
- {
235
- ...consumerProps,
236
- ...className !== void 0 ? { className } : {},
237
- ...onClick !== void 0 ? { onClick } : {},
238
- children
239
- }
240
- );
241
- }
242
- return closeButton;
243
- }
244
- HeaderClose.displayName = "HeaderClose";
245
- const Header = {
246
- Close: HeaderClose,
247
- MobileNav: HeaderMobileNav,
248
- Root: HeaderRoot,
249
- Toggle: HeaderToggle
250
- };
6
+ const Header = { Root: HeaderRoot };
251
7
  export {
252
8
  Header,
253
- HeaderClose,
254
- HeaderMobileNav,
255
- HeaderRoot,
256
- HeaderToggle,
257
- useHeader,
258
- useHeaderScrollState
9
+ HeaderRoot
259
10
  };
260
11
  //# sourceMappingURL=Header.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/header/Header.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useMemo,\n useRef,\n type MouseEvent,\n type ReactElement,\n type SyntheticEvent,\n} from \"react\";\nimport { useIsomorphicLayoutEffect, useMergedRefs } from \"@gunkin/uiify/hooks\";\nimport { createPartContext } from \"@gunkin/uiify/core\";\nimport { useRenderElement } from \"@gunkin/uiify/core/render\";\nimport { Drawer } from \"../drawer/Drawer.js\";\nimport type { DrawerSide } from \"../drawer/types.js\";\nimport { useHeader } from \"./use-header.js\";\nimport { useHeaderScrollState } from \"./use-header-scroll-state.js\";\nimport type {\n HeaderMobileMode,\n HeaderRootProps,\n HeaderContextValue,\n HeaderToggleProps,\n HeaderMobileNavProps,\n HeaderCloseProps,\n} from \"./types.js\";\n\nexport type {\n HeaderBehavior,\n HeaderCloseProps,\n HeaderMobileNavProps,\n HeaderMobileMode,\n HeaderPlacement,\n HeaderRootProps,\n HeaderToggleProps,\n UseHeaderOptions,\n UseHeaderReturn,\n UseHeaderScrollStateOptions,\n UseHeaderScrollStateReturn,\n} from \"./types.js\";\n\nconst [HeaderProvider, useHeaderContext] = createPartContext<HeaderContextValue>(\"Header\");\n\nfunction isDrawerMode(mobileMode: HeaderMobileMode): boolean {\n return mobileMode === \"drawer\" || mobileMode === \"sheet\" || mobileMode === \"fullscreen\";\n}\n\nfunction drawerSide(mobileMode: HeaderMobileMode): DrawerSide {\n if (mobileMode === \"sheet\") return \"bottom\";\n return \"left\";\n}\n\nfunction defaultModal(mobileMode: HeaderMobileMode): boolean {\n return isDrawerMode(mobileMode);\n}\n\nfunction defaultLockScroll(mobileMode: HeaderMobileMode, modal: boolean): boolean {\n return isDrawerMode(mobileMode) && modal;\n}\n\nfunction defaultCloseOnSelect(mobileMode: HeaderMobileMode): boolean {\n return mobileMode !== \"none\";\n}\n\nfunction handleCloseOnSelect(\n event: SyntheticEvent<HTMLElement>,\n closeOnSelect: boolean,\n close: () => void,\n): void {\n if (!closeOnSelect) return;\n const target = event.target;\n if (!(target instanceof Element)) return;\n const activator = target.closest(\"a[href], button:not([disabled])\");\n if (!activator || !event.currentTarget.contains(activator)) return;\n close();\n}\n\nexport function HeaderRoot(props: HeaderRootProps): ReactElement | null {\n const {\n behavior = \"none\",\n children,\n closeOnSelect: closeOnSelectProp,\n defaultOpen,\n hidden: hiddenProp,\n lockScroll: lockScrollProp,\n mobileMode = \"none\",\n modal: modalProp,\n onOpenChange,\n open,\n placement = \"static\",\n scrolled: scrolledProp,\n ...consumerProps\n } = props;\n\n const modal = modalProp ?? defaultModal(mobileMode);\n const lockScroll = lockScrollProp ?? defaultLockScroll(mobileMode, modal);\n const closeOnSelect = closeOnSelectProp ?? defaultCloseOnSelect(mobileMode);\n const toggleRef = useRef<HTMLButtonElement | null>(null);\n const wasOpenRef = useRef(false);\n\n const header = useHeader({\n closeOnSelect,\n mobileMode,\n ...(defaultOpen !== undefined ? { defaultOpen } : {}),\n ...(onOpenChange ? { onOpenChange } : {}),\n ...(open !== undefined ? { open } : {}),\n });\n\n useIsomorphicLayoutEffect(() => {\n if (wasOpenRef.current && !header.open && isDrawerMode(mobileMode)) {\n queueMicrotask(() => toggleRef.current?.focus({ preventScroll: true }));\n }\n wasOpenRef.current = header.open;\n }, [header.open, mobileMode]);\n\n const contextValue = useMemo<HeaderContextValue>(\n () => ({\n ...header,\n behavior,\n hidden: hiddenProp ?? false,\n lockScroll,\n modal,\n placement,\n scrolled: scrolledProp ?? false,\n toggleRef,\n }),\n [behavior, header, hiddenProp, lockScroll, modal, placement, scrolledProp],\n );\n\n const rootElement = useRenderElement({\n defaultTag: \"div\",\n props: {\n ...consumerProps,\n \"data-behavior\": behavior,\n \"data-hidden\": hiddenProp ? \"\" : undefined,\n \"data-lock-scroll\": lockScroll && header.open && isDrawerMode(mobileMode) ? \"\" : undefined,\n \"data-mobile-mode\": mobileMode,\n \"data-state\": header.open ? \"open\" : \"closed\",\n \"data-placement\": placement,\n \"data-scrolled\": scrolledProp ? \"\" : undefined,\n children,\n },\n state: {\n open: header.open,\n placement,\n behavior,\n mobileMode,\n scrolled: scrolledProp ?? false,\n hidden: hiddenProp ?? false,\n },\n });\n\n const tree = <HeaderProvider value={contextValue}>{rootElement}</HeaderProvider>;\n\n if (isDrawerMode(mobileMode)) {\n return (\n <Drawer.Root\n modal={modal}\n onOpenChange={header.setOpen}\n open={header.open}\n side={drawerSide(mobileMode)}\n >\n {tree}\n </Drawer.Root>\n );\n }\n\n return tree;\n}\nHeaderRoot.displayName = \"HeaderRoot\";\n\nexport function HeaderToggle(props: HeaderToggleProps): ReactElement | null {\n const {\n closeLabel = \"Close navigation\",\n openLabel = \"Open navigation\",\n ref,\n onClick,\n ...consumerProps\n } = props;\n const { getToggleProps, mobileMode, open, toggle, toggleRef } = useHeaderContext(\"Toggle\");\n const mergedRef = useMergedRefs(toggleRef, ref);\n const dialogMode = isDrawerMode(mobileMode);\n\n const toggleProps = getToggleProps({\n type: \"button\",\n \"aria-haspopup\": dialogMode ? \"dialog\" : undefined,\n \"aria-label\": open ? closeLabel : openLabel,\n onClick(event: MouseEvent<HTMLButtonElement>) {\n toggle();\n onClick?.(event);\n },\n });\n\n return useRenderElement({\n defaultTag: \"button\",\n props: {\n ...consumerProps,\n ref: mergedRef,\n ...toggleProps,\n },\n state: { open },\n });\n}\n\nexport function HeaderMobileNav(props: HeaderMobileNavProps): ReactElement | null {\n const { children, forceMount, onClick: consumerOnClick, ...consumerProps } = props;\n const { close, closeOnSelect, getMobileNavProps, mobileMode, open } =\n useHeaderContext(\"MobileNav\");\n\n const onClick = useCallback(\n (event: SyntheticEvent<HTMLElement>) => {\n handleCloseOnSelect(event, closeOnSelect, close);\n consumerOnClick?.(event as React.MouseEvent<HTMLElement>);\n },\n [close, closeOnSelect, consumerOnClick],\n );\n\n const noneNav = useRenderElement({\n defaultTag: \"nav\",\n props: {\n ...consumerProps,\n ...getMobileNavProps({ onClick }),\n children,\n },\n state: { open },\n });\n\n const drawerNav = useRenderElement({\n defaultTag: \"nav\",\n props: {\n ...consumerProps,\n ...getMobileNavProps({\n \"data-mobile-mode\": mobileMode,\n \"data-state\": open ? \"open\" : \"closed\",\n onClick,\n }),\n children,\n },\n state: { open, mobileMode },\n });\n\n const collapseNav = useRenderElement({\n defaultTag: \"nav\",\n props: {\n ...consumerProps,\n ...getMobileNavProps({\n \"aria-hidden\": open ? undefined : true,\n \"data-mobile-mode\": mobileMode,\n \"data-state\": open ? \"open\" : \"closed\",\n hidden: open ? undefined : true,\n onClick,\n }),\n children,\n },\n state: { open, mobileMode },\n });\n\n if (mobileMode === \"none\") {\n return noneNav;\n }\n\n if (mobileMode === \"collapse\") {\n if (!open && !forceMount) {\n return null;\n }\n\n return collapseNav;\n }\n\n return <Drawer.Content>{drawerNav}</Drawer.Content>;\n}\nHeaderMobileNav.displayName = \"HeaderMobileNav\";\n\nexport function HeaderClose(props: HeaderCloseProps): ReactElement | null {\n const { children, className, onClick, ...consumerProps } = props;\n const { close, mobileMode } = useHeaderContext(\"Close\");\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n close();\n onClick?.(event);\n };\n\n const closeButton = useRenderElement({\n defaultTag: \"button\",\n props: {\n ...consumerProps,\n type: \"button\",\n onClick: handleClick,\n ...(className !== undefined ? { className } : {}),\n children,\n },\n state: {},\n });\n\n if (isDrawerMode(mobileMode)) {\n return (\n <Drawer.Close\n {...consumerProps}\n {...(className !== undefined ? { className } : {})}\n {...(onClick !== undefined ? { onClick } : {})}\n >\n {children}\n </Drawer.Close>\n );\n }\n\n return closeButton;\n}\nHeaderClose.displayName = \"HeaderClose\";\n\nexport const Header = {\n Close: HeaderClose,\n MobileNav: HeaderMobileNav,\n Root: HeaderRoot,\n Toggle: HeaderToggle,\n};\n\nexport { useHeader, useHeaderScrollState };\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components/header/Header.tsx"],"sourcesContent":["import type { ReactElement } from \"react\";\nimport type { HeaderRootProps } from \"./types.js\";\n\nexport function HeaderRoot({ placement = \"static\", ...props }: HeaderRootProps): ReactElement {\n return <header {...props} data-uiify-header=\"\" data-placement={placement} />;\n}\nHeaderRoot.displayName = \"HeaderRoot\";\n\nexport const Header = { Root: HeaderRoot };\n"],"mappings":"AAIS;AADF,SAAS,WAAW,EAAE,YAAY,UAAU,GAAG,MAAM,GAAkC;AAC5F,SAAO,oBAAC,YAAQ,GAAG,OAAO,qBAAkB,IAAG,kBAAgB,WAAW;AAC5E;AACA,WAAW,cAAc;AAElB,MAAM,SAAS,EAAE,MAAM,WAAW;","names":[]}
@@ -0,0 +1,7 @@
1
+ import type { ReactElement } from "react";
2
+ import type { HeaderClientProps } from "../types.js";
3
+ export declare function HeaderClient({ hideOnScroll, scrollTarget, placement, ref, ...props }: HeaderClientProps): ReactElement;
4
+ export declare namespace HeaderClient {
5
+ var displayName: string;
6
+ }
7
+ //# sourceMappingURL=HeaderClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HeaderClient.d.ts","sourceRoot":"","sources":["../../../../src/components/header/client/HeaderClient.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1C,OAAO,KAAK,EAAE,iBAAiB,EAAqB,MAAM,aAAa,CAAC;AAExE,wBAAgB,YAAY,CAAC,EAC3B,YAAmB,EACnB,YAAY,EACZ,SAAoB,EACpB,GAAG,EACH,GAAG,KAAK,EACT,EAAE,iBAAiB,GAAG,YAAY,CAmFlC;yBAzFe,YAAY"}
@@ -0,0 +1,93 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useEffect, useRef, useState } from "react";
4
+ import { useMergedRefs } from "../../../hooks/use-merged-refs.js";
5
+ import { HeaderRoot } from "../Header.js";
6
+ function HeaderClient({
7
+ hideOnScroll = true,
8
+ scrollTarget,
9
+ placement = "sticky",
10
+ ref,
11
+ ...props
12
+ }) {
13
+ const rootRef = useRef(null);
14
+ const mergedRef = useMergedRefs(rootRef, ref);
15
+ const [state, setState] = useState("top");
16
+ useEffect(() => {
17
+ const root = rootRef.current;
18
+ const view = root?.ownerDocument.defaultView;
19
+ if (!root || !view) return;
20
+ const element = scrollTarget === void 0 ? null : root.ownerDocument.getElementById(scrollTarget);
21
+ const target = scrollTarget === void 0 ? view : element;
22
+ const readPosition = () => {
23
+ return Math.max(0, element ? element.scrollTop : view.scrollY);
24
+ };
25
+ let previous = target ? readPosition() : 0;
26
+ let current = previous === 0 ? "top" : "visible";
27
+ setState(current);
28
+ if (!target) return;
29
+ let height = Infinity;
30
+ let movement = 0;
31
+ let frame = 0;
32
+ const update = (next) => {
33
+ if (current === next) return;
34
+ current = next;
35
+ setState(next);
36
+ };
37
+ const protectedState = () => root.contains(root.ownerDocument.activeElement) || root.querySelector("dialog[open], details[open], :popover-open") !== null;
38
+ const reveal = () => {
39
+ if (protectedState()) {
40
+ movement = 0;
41
+ update(readPosition() === 0 ? "top" : "visible");
42
+ }
43
+ };
44
+ const resize = new view.ResizeObserver((entries) => {
45
+ const entry = entries[0];
46
+ if (entry) height = entry.borderBoxSize[0]?.blockSize ?? entry.contentRect.height;
47
+ });
48
+ resize.observe(root, { box: "border-box" });
49
+ const mutation = new view.MutationObserver(reveal);
50
+ mutation.observe(root, {
51
+ subtree: true,
52
+ childList: true,
53
+ attributes: true,
54
+ attributeFilter: ["open"]
55
+ });
56
+ root.addEventListener("focusin", reveal);
57
+ root.addEventListener("toggle", reveal, true);
58
+ const scroll = () => {
59
+ if (frame) return;
60
+ frame = view.requestAnimationFrame(() => {
61
+ frame = 0;
62
+ const position = readPosition();
63
+ const delta = position - previous;
64
+ previous = position;
65
+ if (position === 0 || !hideOnScroll || placement === "static" || protectedState()) {
66
+ movement = 0;
67
+ update(position === 0 ? "top" : "visible");
68
+ return;
69
+ }
70
+ if (delta !== 0)
71
+ movement = Math.sign(delta) === Math.sign(movement) ? movement + delta : delta;
72
+ if (current === "top") update("visible");
73
+ if (movement <= -8) update("visible");
74
+ if (position > height && movement >= 8) update("hidden");
75
+ });
76
+ };
77
+ target.addEventListener("scroll", scroll, { passive: true });
78
+ return () => {
79
+ target.removeEventListener("scroll", scroll);
80
+ root.removeEventListener("focusin", reveal);
81
+ root.removeEventListener("toggle", reveal, true);
82
+ resize.disconnect();
83
+ mutation.disconnect();
84
+ if (frame) view.cancelAnimationFrame(frame);
85
+ };
86
+ }, [hideOnScroll, scrollTarget, placement]);
87
+ return /* @__PURE__ */ jsx(HeaderRoot, { ...props, placement, ref: mergedRef, "data-state": state });
88
+ }
89
+ HeaderClient.displayName = "HeaderClient";
90
+ export {
91
+ HeaderClient
92
+ };
93
+ //# sourceMappingURL=HeaderClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/components/header/client/HeaderClient.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport type { ReactElement } from \"react\";\nimport { useMergedRefs } from \"../../../hooks/use-merged-refs.js\";\nimport { HeaderRoot } from \"../Header.js\";\nimport type { HeaderClientProps, HeaderClientState } from \"../types.js\";\n\nexport function HeaderClient({\n hideOnScroll = true,\n scrollTarget,\n placement = \"sticky\",\n ref,\n ...props\n}: HeaderClientProps): ReactElement {\n const rootRef = useRef<HTMLElement>(null);\n const mergedRef = useMergedRefs(rootRef, ref);\n const [state, setState] = useState<HeaderClientState>(\"top\");\n\n useEffect(() => {\n const root = rootRef.current;\n const view = root?.ownerDocument.defaultView;\n if (!root || !view) return;\n const element =\n scrollTarget === undefined ? null : root.ownerDocument.getElementById(scrollTarget);\n const target = scrollTarget === undefined ? view : element;\n const readPosition = () => {\n // banned-read-ok: Scroll offset is the required direction input; it does not measure layout.\n return Math.max(0, element ? element.scrollTop : view.scrollY);\n };\n let previous = target ? readPosition() : 0;\n let current: HeaderClientState = previous === 0 ? \"top\" : \"visible\";\n setState(current);\n if (!target) return;\n\n let height = Infinity;\n let movement = 0;\n let frame = 0;\n const update = (next: HeaderClientState) => {\n if (current === next) return;\n current = next;\n setState(next);\n };\n const protectedState = () =>\n root.contains(root.ownerDocument.activeElement) ||\n root.querySelector(\"dialog[open], details[open], :popover-open\") !== null;\n const reveal = () => {\n if (protectedState()) {\n movement = 0;\n update(readPosition() === 0 ? \"top\" : \"visible\");\n }\n };\n const resize = new view.ResizeObserver((entries) => {\n const entry = entries[0];\n if (entry) height = entry.borderBoxSize[0]?.blockSize ?? entry.contentRect.height;\n });\n resize.observe(root, { box: \"border-box\" });\n const mutation = new view.MutationObserver(reveal);\n mutation.observe(root, {\n subtree: true,\n childList: true,\n attributes: true,\n attributeFilter: [\"open\"],\n });\n root.addEventListener(\"focusin\", reveal);\n root.addEventListener(\"toggle\", reveal, true);\n const scroll = () => {\n if (frame) return;\n frame = view.requestAnimationFrame(() => {\n frame = 0;\n const position = readPosition();\n const delta = position - previous;\n previous = position;\n if (position === 0 || !hideOnScroll || placement === \"static\" || protectedState()) {\n movement = 0;\n update(position === 0 ? \"top\" : \"visible\");\n return;\n }\n if (delta !== 0)\n movement = Math.sign(delta) === Math.sign(movement) ? movement + delta : delta;\n if (current === \"top\") update(\"visible\");\n if (movement <= -8) update(\"visible\");\n if (position > height && movement >= 8) update(\"hidden\");\n });\n };\n target.addEventListener(\"scroll\", scroll, { passive: true });\n return () => {\n target.removeEventListener(\"scroll\", scroll);\n root.removeEventListener(\"focusin\", reveal);\n root.removeEventListener(\"toggle\", reveal, true);\n resize.disconnect();\n mutation.disconnect();\n if (frame) view.cancelAnimationFrame(frame);\n };\n }, [hideOnScroll, scrollTarget, placement]);\n\n return <HeaderRoot {...props} placement={placement} ref={mergedRef} data-state={state} />;\n}\nHeaderClient.displayName = \"HeaderClient\";\n"],"mappings":"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","names":[]}
@@ -0,0 +1,3 @@
1
+ export { HeaderClient } from "./HeaderClient.js";
2
+ export type { HeaderClientProps, HeaderClientState } from "../types.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/header/client/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,6 @@
1
+ "use client";
2
+ import { HeaderClient } from "./HeaderClient.js";
3
+ export {
4
+ HeaderClient
5
+ };
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/components/header/client/index.ts"],"sourcesContent":["\"use client\";\n\nexport { HeaderClient } from \"./HeaderClient.js\";\nexport type { HeaderClientProps, HeaderClientState } from \"../types.js\";\n"],"mappings":";AAEA,SAAS,oBAAoB;","names":[]}
@@ -0,0 +1 @@
1
+ export * from "./client/index.js";
@@ -0,0 +1 @@
1
+ export * from "./client/index.js";
@@ -1,4 +1,3 @@
1
- export { Header, HeaderClose, HeaderMobileNav, HeaderRoot, HeaderToggle, useHeaderScrollState, } from "./Header.js";
2
- export { useHeader } from "./use-header.js";
3
- export type { HeaderBehavior, HeaderCloseProps, HeaderMobileNavProps, HeaderMobileMode, HeaderPlacement, HeaderRootProps, HeaderToggleProps, UseHeaderOptions, UseHeaderReturn, UseHeaderScrollStateOptions, UseHeaderScrollStateReturn, } from "./types.js";
1
+ export { Header, HeaderRoot } from "./Header.js";
2
+ export type { HeaderClientProps, HeaderClientState, HeaderPlacement, HeaderRootProps, } from "./types.js";
4
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/header/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,WAAW,EACX,eAAe,EACf,UAAU,EACV,YAAY,EACZ,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/header/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EACV,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC"}
@@ -1,19 +1,6 @@
1
- import {
2
- Header,
3
- HeaderClose,
4
- HeaderMobileNav,
5
- HeaderRoot,
6
- HeaderToggle,
7
- useHeaderScrollState
8
- } from "./Header.js";
9
- import { useHeader } from "./use-header.js";
1
+ import { Header, HeaderRoot } from "./Header.js";
10
2
  export {
11
3
  Header,
12
- HeaderClose,
13
- HeaderMobileNav,
14
- HeaderRoot,
15
- HeaderToggle,
16
- useHeader,
17
- useHeaderScrollState
4
+ HeaderRoot
18
5
  };
19
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/header/index.ts"],"sourcesContent":["export {\n Header,\n HeaderClose,\n HeaderMobileNav,\n HeaderRoot,\n HeaderToggle,\n useHeaderScrollState,\n} from \"./Header.js\";\nexport { useHeader } from \"./use-header.js\";\nexport type {\n HeaderBehavior,\n HeaderCloseProps,\n HeaderMobileNavProps,\n HeaderMobileMode,\n HeaderPlacement,\n HeaderRootProps,\n HeaderToggleProps,\n UseHeaderOptions,\n UseHeaderReturn,\n UseHeaderScrollStateOptions,\n UseHeaderScrollStateReturn,\n} from \"./types.js\";\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAiB;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/header/index.ts"],"sourcesContent":["export { Header, HeaderRoot } from \"./Header.js\";\nexport type {\n HeaderClientProps,\n HeaderClientState,\n HeaderPlacement,\n HeaderRootProps,\n} from \"./types.js\";\n"],"mappings":"AAAA,SAAS,QAAQ,kBAAkB;","names":[]}
@@ -1,67 +1,11 @@
1
- import type { ButtonHTMLAttributes, HTMLAttributes, Ref, RefObject } from "react";
2
- export type HeaderBehavior = "none" | "elevate-on-scroll" | "solid-on-scroll" | "hide-on-scroll-down";
3
- export type HeaderMobileMode = "none" | "collapse" | "drawer" | "sheet" | "fullscreen";
4
- export type HeaderPlacement = "static" | "sticky" | "fixed";
5
- export interface UseHeaderOptions {
6
- readonly closeOnSelect?: boolean;
7
- readonly defaultOpen?: boolean;
8
- readonly mobileMode?: HeaderMobileMode;
9
- readonly onOpenChange?: (open: boolean) => void;
10
- readonly open?: boolean;
11
- }
12
- export interface UseHeaderReturn {
13
- readonly close: () => void;
14
- readonly closeOnSelect: boolean;
15
- readonly getMobileNavProps: <T extends HTMLAttributes<HTMLElement>>(props?: T) => T;
16
- readonly getToggleProps: <T extends ButtonHTMLAttributes<HTMLButtonElement>>(props?: T) => T;
17
- readonly mobileMode: HeaderMobileMode;
18
- readonly navId: string;
19
- readonly open: boolean;
20
- readonly setOpen: (open: boolean) => void;
21
- readonly toggle: () => void;
22
- readonly toggleId: string;
23
- }
24
- export interface HeaderRootProps extends HTMLAttributes<HTMLDivElement> {
25
- readonly behavior?: HeaderBehavior;
26
- readonly closeOnSelect?: boolean;
27
- readonly defaultOpen?: boolean;
28
- readonly hidden?: boolean;
29
- readonly lockScroll?: boolean;
30
- readonly mobileMode?: HeaderMobileMode;
31
- readonly modal?: boolean;
32
- readonly onOpenChange?: (open: boolean) => void;
33
- readonly open?: boolean;
1
+ import type { ComponentPropsWithRef } from "react";
2
+ export type HeaderPlacement = "static" | "sticky";
3
+ export interface HeaderRootProps extends ComponentPropsWithRef<"header"> {
34
4
  readonly placement?: HeaderPlacement;
35
- readonly scrolled?: boolean;
36
- }
37
- export interface HeaderContextValue extends UseHeaderReturn {
38
- readonly behavior: HeaderBehavior;
39
- readonly hidden: boolean;
40
- readonly lockScroll: boolean;
41
- readonly modal: boolean;
42
- readonly placement: HeaderPlacement;
43
- readonly scrolled: boolean;
44
- readonly toggleRef: RefObject<HTMLButtonElement | null>;
45
- }
46
- export interface HeaderToggleProps extends ButtonHTMLAttributes<HTMLButtonElement> {
47
- readonly closeLabel?: string;
48
- readonly openLabel?: string;
49
- readonly ref?: Ref<HTMLButtonElement>;
50
- }
51
- export interface HeaderMobileNavProps extends HTMLAttributes<HTMLElement> {
52
- readonly forceMount?: boolean;
53
- }
54
- export interface HeaderCloseProps extends ButtonHTMLAttributes<HTMLButtonElement> {
55
- }
56
- export interface UseHeaderScrollStateOptions {
57
- readonly behavior?: HeaderBehavior;
58
- readonly disabled?: boolean;
59
- readonly scrollRoot?: HTMLElement | null;
60
- readonly scrollRootRef?: RefObject<HTMLElement | null>;
61
- readonly threshold?: number;
62
5
  }
63
- export interface UseHeaderScrollStateReturn {
64
- readonly hidden: boolean;
65
- readonly scrolled: boolean;
6
+ export type HeaderClientState = "top" | "visible" | "hidden";
7
+ export interface HeaderClientProps extends HeaderRootProps {
8
+ readonly hideOnScroll?: boolean;
9
+ readonly scrollTarget?: string;
66
10
  }
67
11
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/header/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/header/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAC;AAEnD,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAElD,MAAM,WAAW,eAAgB,SAAQ,qBAAqB,CAAC,QAAQ,CAAC;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC;CACtC;AAED,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE7D,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gunkin/uiify",
3
- "version": "0.0.11-alpha",
3
+ "version": "0.0.12-alpha",
4
4
  "description": "Native-first, accessible React 19 components that work before hydration.",
5
5
  "keywords": [
6
6
  "accessibility",
@@ -1,4 +0,0 @@
1
- import type { UseHeaderScrollStateOptions, UseHeaderScrollStateReturn } from "./types.js";
2
- export type { HeaderBehavior, UseHeaderScrollStateOptions, UseHeaderScrollStateReturn, } from "./types.js";
3
- export declare function useHeaderScrollState(options?: UseHeaderScrollStateOptions): UseHeaderScrollStateReturn;
4
- //# sourceMappingURL=use-header-scroll-state.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-header-scroll-state.d.ts","sourceRoot":"","sources":["../../../src/components/header/use-header-scroll-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,2BAA2B,EAC3B,0BAA0B,EAC3B,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,cAAc,EACd,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,YAAY,CAAC;AAcpB,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,2BAAgC,GACxC,0BAA0B,CAqF5B"}
@@ -1,83 +0,0 @@
1
- "use client";
2
- import { useEffect, useState } from "react";
3
- function isScrollBehavior(behavior) {
4
- return behavior === "elevate-on-scroll" || behavior === "solid-on-scroll" || behavior === "hide-on-scroll-down";
5
- }
6
- function usesIntersectionObserver(behavior) {
7
- return behavior === "elevate-on-scroll" || behavior === "solid-on-scroll";
8
- }
9
- function useHeaderScrollState(options = {}) {
10
- const {
11
- behavior = "none",
12
- disabled = false,
13
- scrollRoot: scrollRootProp,
14
- scrollRootRef,
15
- threshold = 0
16
- } = options;
17
- const scrollRoot = scrollRootProp ?? scrollRootRef?.current ?? null;
18
- const [scrolled, setScrolled] = useState(false);
19
- const [hidden, setHidden] = useState(false);
20
- useEffect(() => {
21
- if (disabled || typeof window === "undefined" || typeof document === "undefined") {
22
- return;
23
- }
24
- if (!isScrollBehavior(behavior)) {
25
- return;
26
- }
27
- if (scrollRootRef && !scrollRoot) {
28
- return;
29
- }
30
- if (usesIntersectionObserver(behavior)) {
31
- const sentinel = document.createElement("div");
32
- sentinel.setAttribute("aria-hidden", "true");
33
- sentinel.setAttribute("data-header-scroll-sentinel", "");
34
- sentinel.style.cssText = "position:absolute;top:0;left:0;width:1px;height:1px;pointer-events:none;visibility:hidden";
35
- if (scrollRoot) {
36
- scrollRoot.insertBefore(sentinel, scrollRoot.firstChild);
37
- } else {
38
- document.body.prepend(sentinel);
39
- }
40
- const rootMargin = threshold > 0 ? `-${threshold}px 0px 0px 0px` : "0px";
41
- const observer = new IntersectionObserver(
42
- (entries) => {
43
- const entry = entries[0];
44
- if (!entry) return;
45
- setScrolled(!entry.isIntersecting);
46
- },
47
- { root: scrollRoot, rootMargin, threshold: 0 }
48
- );
49
- observer.observe(sentinel);
50
- return () => {
51
- observer.disconnect();
52
- sentinel.remove();
53
- };
54
- }
55
- if (behavior === "hide-on-scroll-down") {
56
- let lastScrollTop = scrollRoot ? scrollRoot.scrollTop : window.scrollY;
57
- let ticking = false;
58
- const readScrollTop = () => scrollRoot ? scrollRoot.scrollTop : window.scrollY;
59
- const update = () => {
60
- const currentScrollTop = readScrollTop();
61
- const pastThreshold = currentScrollTop > threshold;
62
- setScrolled(pastThreshold);
63
- setHidden(pastThreshold && currentScrollTop > lastScrollTop);
64
- lastScrollTop = currentScrollTop;
65
- ticking = false;
66
- };
67
- const onScroll = () => {
68
- if (ticking) return;
69
- ticking = true;
70
- requestAnimationFrame(update);
71
- };
72
- const target = scrollRoot ?? window;
73
- target.addEventListener("scroll", onScroll, { passive: true });
74
- return () => target.removeEventListener("scroll", onScroll);
75
- }
76
- return void 0;
77
- }, [behavior, disabled, scrollRoot, scrollRootRef, threshold]);
78
- return { hidden, scrolled };
79
- }
80
- export {
81
- useHeaderScrollState
82
- };
83
- //# sourceMappingURL=use-header-scroll-state.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/components/header/use-header-scroll-state.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type {\n HeaderBehavior,\n UseHeaderScrollStateOptions,\n UseHeaderScrollStateReturn,\n} from \"./types.js\";\n\nexport type {\n HeaderBehavior,\n UseHeaderScrollStateOptions,\n UseHeaderScrollStateReturn,\n} from \"./types.js\";\n\nfunction isScrollBehavior(behavior: HeaderBehavior): boolean {\n return (\n behavior === \"elevate-on-scroll\" ||\n behavior === \"solid-on-scroll\" ||\n behavior === \"hide-on-scroll-down\"\n );\n}\n\nfunction usesIntersectionObserver(behavior: HeaderBehavior): boolean {\n return behavior === \"elevate-on-scroll\" || behavior === \"solid-on-scroll\";\n}\n\nexport function useHeaderScrollState(\n options: UseHeaderScrollStateOptions = {},\n): UseHeaderScrollStateReturn {\n const {\n behavior = \"none\",\n disabled = false,\n scrollRoot: scrollRootProp,\n scrollRootRef,\n threshold = 0,\n } = options;\n const scrollRoot = scrollRootProp ?? scrollRootRef?.current ?? null;\n const [scrolled, setScrolled] = useState(false);\n const [hidden, setHidden] = useState(false);\n\n useEffect(() => {\n if (disabled || typeof window === \"undefined\" || typeof document === \"undefined\") {\n return;\n }\n\n if (!isScrollBehavior(behavior)) {\n return;\n }\n\n if (scrollRootRef && !scrollRoot) {\n return;\n }\n\n if (usesIntersectionObserver(behavior)) {\n const sentinel = document.createElement(\"div\");\n sentinel.setAttribute(\"aria-hidden\", \"true\");\n sentinel.setAttribute(\"data-header-scroll-sentinel\", \"\");\n sentinel.style.cssText =\n \"position:absolute;top:0;left:0;width:1px;height:1px;pointer-events:none;visibility:hidden\";\n\n if (scrollRoot) {\n scrollRoot.insertBefore(sentinel, scrollRoot.firstChild);\n } else {\n document.body.prepend(sentinel);\n }\n\n const rootMargin = threshold > 0 ? `-${threshold}px 0px 0px 0px` : \"0px\";\n const observer = new IntersectionObserver(\n (entries) => {\n const entry = entries[0];\n if (!entry) return;\n setScrolled(!entry.isIntersecting);\n },\n { root: scrollRoot, rootMargin, threshold: 0 },\n );\n observer.observe(sentinel);\n\n return () => {\n observer.disconnect();\n sentinel.remove();\n };\n }\n\n if (behavior === \"hide-on-scroll-down\") {\n let lastScrollTop = scrollRoot ? scrollRoot.scrollTop : window.scrollY; // banned-read-ok: scroll handler, batched in rAF\n let ticking = false;\n\n const readScrollTop = (): number => (scrollRoot ? scrollRoot.scrollTop : window.scrollY); // banned-read-ok: scroll handler, batched in rAF\n\n const update = () => {\n const currentScrollTop = readScrollTop();\n const pastThreshold = currentScrollTop > threshold;\n setScrolled(pastThreshold);\n setHidden(pastThreshold && currentScrollTop > lastScrollTop);\n lastScrollTop = currentScrollTop;\n ticking = false;\n };\n\n const onScroll = () => {\n if (ticking) return;\n ticking = true;\n requestAnimationFrame(update);\n };\n\n const target: HTMLElement | Window = scrollRoot ?? window;\n target.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => target.removeEventListener(\"scroll\", onScroll);\n }\n\n return undefined;\n }, [behavior, disabled, scrollRoot, scrollRootRef, threshold]);\n\n return { hidden, scrolled };\n}\n"],"mappings":";AAEA,SAAS,WAAW,gBAAgB;AAapC,SAAS,iBAAiB,UAAmC;AAC3D,SACE,aAAa,uBACb,aAAa,qBACb,aAAa;AAEjB;AAEA,SAAS,yBAAyB,UAAmC;AACnE,SAAO,aAAa,uBAAuB,aAAa;AAC1D;AAEO,SAAS,qBACd,UAAuC,CAAC,GACZ;AAC5B,QAAM;AAAA,IACJ,WAAW;AAAA,IACX,WAAW;AAAA,IACX,YAAY;AAAA,IACZ;AAAA,IACA,YAAY;AAAA,EACd,IAAI;AACJ,QAAM,aAAa,kBAAkB,eAAe,WAAW;AAC/D,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAE1C,YAAU,MAAM;AACd,QAAI,YAAY,OAAO,WAAW,eAAe,OAAO,aAAa,aAAa;AAChF;AAAA,IACF;AAEA,QAAI,CAAC,iBAAiB,QAAQ,GAAG;AAC/B;AAAA,IACF;AAEA,QAAI,iBAAiB,CAAC,YAAY;AAChC;AAAA,IACF;AAEA,QAAI,yBAAyB,QAAQ,GAAG;AACtC,YAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,eAAS,aAAa,eAAe,MAAM;AAC3C,eAAS,aAAa,+BAA+B,EAAE;AACvD,eAAS,MAAM,UACb;AAEF,UAAI,YAAY;AACd,mBAAW,aAAa,UAAU,WAAW,UAAU;AAAA,MACzD,OAAO;AACL,iBAAS,KAAK,QAAQ,QAAQ;AAAA,MAChC;AAEA,YAAM,aAAa,YAAY,IAAI,IAAI,SAAS,mBAAmB;AACnE,YAAM,WAAW,IAAI;AAAA,QACnB,CAAC,YAAY;AACX,gBAAM,QAAQ,QAAQ,CAAC;AACvB,cAAI,CAAC,MAAO;AACZ,sBAAY,CAAC,MAAM,cAAc;AAAA,QACnC;AAAA,QACA,EAAE,MAAM,YAAY,YAAY,WAAW,EAAE;AAAA,MAC/C;AACA,eAAS,QAAQ,QAAQ;AAEzB,aAAO,MAAM;AACX,iBAAS,WAAW;AACpB,iBAAS,OAAO;AAAA,MAClB;AAAA,IACF;AAEA,QAAI,aAAa,uBAAuB;AACtC,UAAI,gBAAgB,aAAa,WAAW,YAAY,OAAO;AAC/D,UAAI,UAAU;AAEd,YAAM,gBAAgB,MAAe,aAAa,WAAW,YAAY,OAAO;AAEhF,YAAM,SAAS,MAAM;AACnB,cAAM,mBAAmB,cAAc;AACvC,cAAM,gBAAgB,mBAAmB;AACzC,oBAAY,aAAa;AACzB,kBAAU,iBAAiB,mBAAmB,aAAa;AAC3D,wBAAgB;AAChB,kBAAU;AAAA,MACZ;AAEA,YAAM,WAAW,MAAM;AACrB,YAAI,QAAS;AACb,kBAAU;AACV,8BAAsB,MAAM;AAAA,MAC9B;AAEA,YAAM,SAA+B,cAAc;AACnD,aAAO,iBAAiB,UAAU,UAAU,EAAE,SAAS,KAAK,CAAC;AAC7D,aAAO,MAAM,OAAO,oBAAoB,UAAU,QAAQ;AAAA,IAC5D;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,UAAU,UAAU,YAAY,eAAe,SAAS,CAAC;AAE7D,SAAO,EAAE,QAAQ,SAAS;AAC5B;","names":[]}
@@ -1,4 +0,0 @@
1
- import type { UseHeaderOptions, UseHeaderReturn } from "./types.js";
2
- export type { HeaderMobileMode, UseHeaderOptions, UseHeaderReturn } from "./types.js";
3
- export declare function useHeader(options?: UseHeaderOptions): UseHeaderReturn;
4
- //# sourceMappingURL=use-header.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-header.d.ts","sourceRoot":"","sources":["../../../src/components/header/use-header.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAoB,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEtF,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAatF,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,eAAe,CAuEzE"}
@@ -1,80 +0,0 @@
1
- "use client";
2
- import { useCallback, useMemo } from "react";
3
- import { useControllableState, useId } from "@gunkin/uiify/hooks";
4
- function isDrawerMobileMode(mobileMode) {
5
- return mobileMode === "drawer" || mobileMode === "sheet" || mobileMode === "fullscreen";
6
- }
7
- function exposesNavControls(mobileMode, open) {
8
- if (mobileMode === "none") return false;
9
- if (isDrawerMobileMode(mobileMode)) return true;
10
- if (mobileMode === "collapse") return true;
11
- return open;
12
- }
13
- function useHeader(options = {}) {
14
- const {
15
- closeOnSelect = true,
16
- defaultOpen = false,
17
- mobileMode = "none",
18
- onOpenChange,
19
- open: controlledOpen
20
- } = options;
21
- const navId = useId();
22
- const toggleId = useId();
23
- const [open, setOpen] = useControllableState({
24
- defaultValue: defaultOpen,
25
- onChange: onOpenChange,
26
- value: controlledOpen
27
- });
28
- const toggle = useCallback(() => {
29
- setOpen((current) => !current);
30
- }, [setOpen]);
31
- const close = useCallback(() => {
32
- setOpen(false);
33
- }, [setOpen]);
34
- const getToggleProps = useCallback(
35
- (props) => ({
36
- ...props,
37
- id: toggleId,
38
- ...exposesNavControls(mobileMode, open) ? { "aria-controls": navId } : {},
39
- "aria-expanded": open
40
- }),
41
- [mobileMode, navId, open, toggleId]
42
- );
43
- const getMobileNavProps = useCallback(
44
- (props) => ({
45
- ...props,
46
- id: navId
47
- }),
48
- [navId]
49
- );
50
- return useMemo(
51
- () => ({
52
- close,
53
- closeOnSelect,
54
- getMobileNavProps,
55
- getToggleProps,
56
- mobileMode,
57
- navId,
58
- open,
59
- setOpen,
60
- toggle,
61
- toggleId
62
- }),
63
- [
64
- close,
65
- closeOnSelect,
66
- getMobileNavProps,
67
- getToggleProps,
68
- mobileMode,
69
- navId,
70
- open,
71
- setOpen,
72
- toggle,
73
- toggleId
74
- ]
75
- );
76
- }
77
- export {
78
- useHeader
79
- };
80
- //# sourceMappingURL=use-header.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/components/header/use-header.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useMemo } from \"react\";\nimport type { ButtonHTMLAttributes, HTMLAttributes } from \"react\";\nimport { useControllableState, useId } from \"@gunkin/uiify/hooks\";\nimport type { HeaderMobileMode, UseHeaderOptions, UseHeaderReturn } from \"./types.js\";\n\nexport type { HeaderMobileMode, UseHeaderOptions, UseHeaderReturn } from \"./types.js\";\n\nfunction isDrawerMobileMode(mobileMode: HeaderMobileMode): boolean {\n return mobileMode === \"drawer\" || mobileMode === \"sheet\" || mobileMode === \"fullscreen\";\n}\n\nfunction exposesNavControls(mobileMode: HeaderMobileMode, open: boolean): boolean {\n if (mobileMode === \"none\") return false;\n if (isDrawerMobileMode(mobileMode)) return true;\n if (mobileMode === \"collapse\") return true;\n return open;\n}\n\nexport function useHeader(options: UseHeaderOptions = {}): UseHeaderReturn {\n const {\n closeOnSelect = true,\n defaultOpen = false,\n mobileMode = \"none\",\n onOpenChange,\n open: controlledOpen,\n } = options;\n\n const navId = useId();\n const toggleId = useId();\n const [open, setOpen] = useControllableState({\n defaultValue: defaultOpen,\n onChange: onOpenChange,\n value: controlledOpen,\n });\n\n const toggle = useCallback(() => {\n setOpen((current) => !current);\n }, [setOpen]);\n\n const close = useCallback(() => {\n setOpen(false);\n }, [setOpen]);\n\n const getToggleProps = useCallback(\n <T extends ButtonHTMLAttributes<HTMLButtonElement>>(props?: T): T =>\n ({\n ...props,\n id: toggleId,\n ...(exposesNavControls(mobileMode, open) ? { \"aria-controls\": navId } : {}),\n \"aria-expanded\": open,\n }) as T,\n [mobileMode, navId, open, toggleId],\n );\n\n const getMobileNavProps = useCallback(\n <T extends HTMLAttributes<HTMLElement>>(props?: T): T =>\n ({\n ...props,\n id: navId,\n }) as T,\n [navId],\n );\n\n return useMemo(\n () => ({\n close,\n closeOnSelect,\n getMobileNavProps,\n getToggleProps,\n mobileMode,\n navId,\n open,\n setOpen,\n toggle,\n toggleId,\n }),\n [\n close,\n closeOnSelect,\n getMobileNavProps,\n getToggleProps,\n mobileMode,\n navId,\n open,\n setOpen,\n toggle,\n toggleId,\n ],\n );\n}\n"],"mappings":";AAEA,SAAS,aAAa,eAAe;AAErC,SAAS,sBAAsB,aAAa;AAK5C,SAAS,mBAAmB,YAAuC;AACjE,SAAO,eAAe,YAAY,eAAe,WAAW,eAAe;AAC7E;AAEA,SAAS,mBAAmB,YAA8B,MAAwB;AAChF,MAAI,eAAe,OAAQ,QAAO;AAClC,MAAI,mBAAmB,UAAU,EAAG,QAAO;AAC3C,MAAI,eAAe,WAAY,QAAO;AACtC,SAAO;AACT;AAEO,SAAS,UAAU,UAA4B,CAAC,GAAoB;AACzE,QAAM;AAAA,IACJ,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,aAAa;AAAA,IACb;AAAA,IACA,MAAM;AAAA,EACR,IAAI;AAEJ,QAAM,QAAQ,MAAM;AACpB,QAAM,WAAW,MAAM;AACvB,QAAM,CAAC,MAAM,OAAO,IAAI,qBAAqB;AAAA,IAC3C,cAAc;AAAA,IACd,UAAU;AAAA,IACV,OAAO;AAAA,EACT,CAAC;AAED,QAAM,SAAS,YAAY,MAAM;AAC/B,YAAQ,CAAC,YAAY,CAAC,OAAO;AAAA,EAC/B,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,QAAQ,YAAY,MAAM;AAC9B,YAAQ,KAAK;AAAA,EACf,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,iBAAiB;AAAA,IACrB,CAAoD,WACjD;AAAA,MACC,GAAG;AAAA,MACH,IAAI;AAAA,MACJ,GAAI,mBAAmB,YAAY,IAAI,IAAI,EAAE,iBAAiB,MAAM,IAAI,CAAC;AAAA,MACzE,iBAAiB;AAAA,IACnB;AAAA,IACF,CAAC,YAAY,OAAO,MAAM,QAAQ;AAAA,EACpC;AAEA,QAAM,oBAAoB;AAAA,IACxB,CAAwC,WACrC;AAAA,MACC,GAAG;AAAA,MACH,IAAI;AAAA,IACN;AAAA,IACF,CAAC,KAAK;AAAA,EACR;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;","names":[]}