@dsn-starter-kit/components-react 3.4.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Card/Card.d.mts +86 -21
- package/dist/Card/Card.d.mts.map +1 -1
- package/dist/Card/Card2.mjs +100 -17
- package/dist/Card/Card2.mjs.map +1 -1
- package/dist/Card/index.d.mts +2 -2
- package/dist/DateInput/DateInput.d.mts +1 -1
- package/dist/DateInput/DateInput.d.mts.map +1 -1
- package/dist/DateInput/DateInput2.mjs +1 -2
- package/dist/DateInput/DateInput2.mjs.map +1 -1
- package/dist/DateInputGroup/DateInputGroup2.mjs +3 -3
- package/dist/DateInputGroup/DateInputGroup2.mjs.map +1 -1
- package/dist/Drawer/Drawer.d.mts +11 -3
- package/dist/Drawer/Drawer.d.mts.map +1 -1
- package/dist/Drawer/Drawer2.mjs +28 -4
- package/dist/Drawer/Drawer2.mjs.map +1 -1
- package/dist/EmailInput/EmailInput.d.mts +10 -5
- package/dist/EmailInput/EmailInput.d.mts.map +1 -1
- package/dist/EmailInput/EmailInput2.mjs +2 -2
- package/dist/EmailInput/EmailInput2.mjs.map +1 -1
- package/dist/ModalDialog/ModalDialog.d.mts +12 -2
- package/dist/ModalDialog/ModalDialog.d.mts.map +1 -1
- package/dist/ModalDialog/ModalDialog2.mjs +35 -8
- package/dist/ModalDialog/ModalDialog2.mjs.map +1 -1
- package/dist/NumberInput/NumberInput.d.mts +4 -4
- package/dist/NumberInput/NumberInput.d.mts.map +1 -1
- package/dist/NumberInput/NumberInput2.mjs +2 -2
- package/dist/NumberInput/NumberInput2.mjs.map +1 -1
- package/dist/PageHeader/PageHeader.d.mts.map +1 -1
- package/dist/PageHeader/PageHeader2.mjs +20 -2
- package/dist/PageHeader/PageHeader2.mjs.map +1 -1
- package/dist/PasswordInput/PasswordInput.d.mts +10 -5
- package/dist/PasswordInput/PasswordInput.d.mts.map +1 -1
- package/dist/PasswordInput/PasswordInput2.mjs +2 -2
- package/dist/PasswordInput/PasswordInput2.mjs.map +1 -1
- package/dist/SearchInput/SearchInput.d.mts +10 -5
- package/dist/SearchInput/SearchInput.d.mts.map +1 -1
- package/dist/SearchInput/SearchInput2.mjs +2 -3
- package/dist/SearchInput/SearchInput2.mjs.map +1 -1
- package/dist/Select/Select.d.mts +6 -6
- package/dist/Select/Select.d.mts.map +1 -1
- package/dist/Select/Select2.mjs +4 -5
- package/dist/Select/Select2.mjs.map +1 -1
- package/dist/TelephoneInput/TelephoneInput.d.mts +10 -5
- package/dist/TelephoneInput/TelephoneInput.d.mts.map +1 -1
- package/dist/TelephoneInput/TelephoneInput2.mjs +2 -2
- package/dist/TelephoneInput/TelephoneInput2.mjs.map +1 -1
- package/dist/TextArea/TextArea.d.mts +10 -5
- package/dist/TextArea/TextArea.d.mts.map +1 -1
- package/dist/TextArea/TextArea2.mjs +2 -2
- package/dist/TextArea/TextArea2.mjs.map +1 -1
- package/dist/TextInput/TextInput.d.mts +4 -4
- package/dist/TextInput/TextInput.d.mts.map +1 -1
- package/dist/TextInput/TextInput2.mjs +2 -2
- package/dist/TextInput/TextInput2.mjs.map +1 -1
- package/dist/TimeInput/TimeInput.d.mts +1 -1
- package/dist/TimeInput/TimeInput.d.mts.map +1 -1
- package/dist/TimeInput/TimeInput2.mjs +1 -2
- package/dist/TimeInput/TimeInput2.mjs.map +1 -1
- package/dist/index.cjs +303 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +5439 -3838
- package/dist/index.d.cts +163 -55
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/utils/focusTrap.mjs +99 -0
- package/dist/utils/focusTrap.mjs.map +1 -0
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageHeader2.mjs","names":[],"sources":["../../src/PageHeader/PageHeader.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames } from '@dsn-starter-kit/core';\nimport { Button } from '../Button';\nimport { Icon } from '../Icon';\nimport { SearchInput } from '../SearchInput';\nimport { Drawer, DrawerBody, DrawerHeader, DrawerHeading } from '../Drawer';\nimport { Stack } from '../Stack';\nimport './PageHeader.css';\n\nexport type PageHeaderSticky = 'none' | 'sticky' | 'auto-hide';\nexport type PageHeaderLayout = 'default' | 'compact';\nexport type PageHeaderColorScheme = 'default' | 'inverse';\n\nexport interface PageHeaderProps extends Omit<\n React.HTMLAttributes<HTMLElement>,\n 'children'\n> {\n /**\n * Logo-inhoud — `<svg>`, `<img>`, of een `<a>` die een logo omhult.\n * De CSS past automatisch `max-block-size` toe op de directe child.\n */\n logoSlot: React.ReactNode;\n\n /**\n * Scrollgedrag van de header.\n * - `none` (standaard): header scrollt mee met de pagina\n * - `sticky`: header blijft bovenaan de viewport vastgeplakt\n * - `auto-hide`: sticky + verbergt bij scroll-down, toont bij scroll-up\n * @default 'none'\n */\n sticky?: PageHeaderSticky;\n\n /**\n * Lay-out van de header op large viewport (≥ 64em).\n * - `default`: twee horizontale banden — Masthead (logo + servicemenu + zoekveld)\n * en Navigatiebalk (primaire navigatie op accent-1 achtergrond)\n * - `compact`: één enkele rij — logo (inline-start), primaire navigatie (gecentreerd),\n * servicemenu + zoekknop (inline-end). Geeft `primaryNavigationLarge` voorrang\n * boven `primaryNavigation` (en idem voor secondary) zodat de Drawer altijd\n * de verticale variant ontvangt.\n * @default 'default'\n */\n layout?: PageHeaderLayout;\n\n /**\n * Kleurschema van de header.\n * - `default`: neutrale achtergrond met accent-1 navbar\n * - `inverse`: sterke accent-1-inverse achtergrond op navbar en compact balk\n * voor prominente branding. Het masthead blijft altijd neutraal.\n * Logo-kleuren passen zich automatisch aan via CSS context overrides.\n * @default 'default'\n */\n colorScheme?: PageHeaderColorScheme;\n\n /**\n * Initiële open-staat van het zoekpaneel (small viewport).\n * Handig voor Storybook en tests — het paneel kan daarna nog steeds\n * worden geopend/gesloten via de knop.\n * @default false\n */\n initialSearchOpen?: boolean;\n\n /**\n * Primaire navigatie-inhoud in de Drawer (small viewport) — doorgaans een verticale `<Menu>` met\n * `<MenuLink>`-items inclusief uitklapmogelijkheden voor sub-niveaus.\n */\n primaryNavigation?: React.ReactNode;\n\n /**\n * Primaire navigatie-inhoud in de Navigatiebalk (large viewport) — doorgaans een horizontale\n * `<Menu>` met alleen Level 1 `<MenuLink>`-items. Als niet meegegeven valt de component\n * terug op `primaryNavigation`.\n */\n primaryNavigationLarge?: React.ReactNode;\n\n /**\n * Servicemenu-inhoud in de Drawer (small viewport) — doorgaans een verticale `<Menu>`.\n */\n secondaryNavigation?: React.ReactNode;\n\n /**\n * Servicemenu-inhoud in de Masthead (large viewport) — doorgaans een horizontale `<Menu>`.\n * Als niet meegegeven valt de component terug op `secondaryNavigation`.\n */\n secondaryNavigationLarge?: React.ReactNode;\n\n /**\n * Inline zoekveld voor de Masthead op large viewport (SearchInput + zoekknop).\n * Optioneel — toont geen zoekveld als weggelaten.\n */\n searchSlot?: React.ReactNode;\n\n /**\n * Visuele badge-indicator bij de menuknop (small viewport), doorgaans een `<DotBadge>`.\n * Gebruik dit om ongelezen meldingen te signaleren. De badge is altijd `aria-hidden` —\n * geef de toegankelijke tekst mee via `menuButtonBadgeLabel`.\n */\n menuButtonBadge?: React.ReactNode;\n\n /**\n * Toegankelijke tekst die wordt toegevoegd aan het label van de menuknop als er een badge\n * aanwezig is, bijvoorbeeld `\"2 nieuwe berichten\"`. Wordt visueel verborgen getoond zodat\n * screenreadergebruikers de melding horen: \"Menu, 2 nieuwe berichten\".\n * Vereist als `menuButtonBadge` is meegegeven.\n */\n menuButtonBadgeLabel?: string;\n\n /**\n * Callback wanneer de navigatielade opent.\n */\n onMenuOpen?: () => void;\n\n /**\n * Callback wanneer de navigatielade sluit.\n */\n onMenuClose?: () => void;\n\n /**\n * Callback wanneer het zoekpaneel opent.\n */\n onSearchOpen?: () => void;\n\n /**\n * Callback wanneer het zoekpaneel sluit.\n */\n onSearchClose?: () => void;\n\n // ── i18n labels ────────────────────────────────────────────────────────────\n\n /**\n * Label van de menuknop en de Drawer-heading.\n * @default 'Menu'\n */\n menuButtonLabel?: string;\n\n /**\n * Label van de zoekknop wanneer het zoekpaneel gesloten is.\n * @default 'Zoeken'\n */\n searchButtonLabel?: string;\n\n /**\n * Label van de zoekknop wanneer het zoekpaneel open is.\n * @default 'Sluiten'\n */\n closeButtonLabel?: string;\n\n /**\n * Placeholder van het zoekveld in het zoekpaneel (small viewport en compact layout).\n * @default 'Zoeken…'\n */\n searchInputPlaceholder?: string;\n\n /**\n * `aria-label` van het zoekveld in het zoekpaneel.\n * @default 'Zoekopdracht'\n */\n searchInputAriaLabel?: string;\n\n /**\n * Label van de zoek-submitknop in het zoekpaneel.\n * @default 'Zoeken'\n */\n searchSubmitLabel?: string;\n\n /**\n * `aria-label` van de primaire navigatie-`<nav>` (large viewport) en\n * visueel verborgen heading in de Drawer.\n * @default 'Hoofd-navigatie'\n */\n primaryNavAriaLabel?: string;\n\n /**\n * `aria-label` van het servicemenu-`<nav>` (large viewport) en\n * visueel verborgen heading in de Drawer.\n * @default 'Service-navigatie'\n */\n secondaryNavAriaLabel?: string;\n\n /**\n * Verbergt de menuknop in de small viewport layout.\n * Gebruik dit wanneer er geen navigatie aanwezig is (bijv. formulierpagina's).\n * @default false\n */\n hideMenuButton?: boolean;\n\n /**\n * Verbergt de zoekknop in zowel de small viewport als compact layout.\n * Gebruik dit wanneer zoeken niet relevant is (bijv. formulierpagina's).\n * @default false\n */\n hideSearchButton?: boolean;\n\n className?: string;\n}\n\n/**\n * PageHeader component\n * Primaire navigatieheader voor een pagina. Mobile-first implementatie.\n *\n * Op mobile toont de header drie elementen:\n * - Menuknop (inline-start) — opent een `Drawer` met primaire en service-navigatie\n * - Logo (gecentreerd, onafhankelijk van knopbreedte via CSS-grid 1fr auto 1fr)\n * - Zoekknop (inline-end) — opent een zoekpaneel direct onder de header\n *\n * @example\n * ```tsx\n * <PageHeader\n * logoSlot={\n * <a href=\"/\">\n * <Logo aria-hidden={true} />\n * <span className=\"dsn-visually-hidden\">Starter Kit — terug naar homepage</span>\n * </a>\n * }\n * primaryNavigation={\n * <Menu orientation=\"vertical\">\n * <MenuLink href=\"/home\" level={1}>Home</MenuLink>\n * <MenuLink href=\"/over\" level={1}>Over ons</MenuLink>\n * </Menu>\n * }\n * secondaryNavigation={\n * <Menu orientation=\"vertical\">\n * <MenuLink href=\"/contact\" level={1}>Contact</MenuLink>\n * </Menu>\n * }\n * />\n * ```\n */\nexport const PageHeader = React.forwardRef<HTMLElement, PageHeaderProps>(\n (\n {\n className,\n logoSlot,\n sticky = 'none',\n layout = 'default',\n colorScheme = 'default',\n initialSearchOpen = false,\n primaryNavigation,\n primaryNavigationLarge,\n secondaryNavigation,\n secondaryNavigationLarge,\n searchSlot,\n menuButtonBadge,\n menuButtonBadgeLabel,\n onMenuOpen,\n onMenuClose,\n onSearchOpen,\n onSearchClose,\n menuButtonLabel = 'Menu',\n searchButtonLabel = 'Zoeken',\n closeButtonLabel = 'Sluiten',\n searchInputPlaceholder = 'Zoeken…',\n searchInputAriaLabel = 'Zoekopdracht',\n searchSubmitLabel = 'Zoeken',\n primaryNavAriaLabel = 'Hoofd-navigatie',\n secondaryNavAriaLabel = 'Service-navigatie',\n hideMenuButton = false,\n hideSearchButton = false,\n ...props\n },\n ref\n ) => {\n const [isMenuOpen, setIsMenuOpen] = React.useState(false);\n const [isSearchOpen, setIsSearchOpen] = React.useState(initialSearchOpen);\n\n const headerRef = React.useRef<HTMLElement>(null);\n const combinedRef = (ref as React.RefObject<HTMLElement>) ?? headerRef;\n\n const menuButtonRef = React.useRef<HTMLButtonElement>(null);\n const searchButtonRef = React.useRef<HTMLButtonElement>(null);\n const searchInputRef = React.useRef<HTMLInputElement>(null);\n const compactSearchButtonRef = React.useRef<HTMLButtonElement>(null);\n const compactSearchInputRef = React.useRef<HTMLInputElement>(null);\n\n const searchPanelId = React.useId();\n const compactSearchPanelId = React.useId();\n\n // Auto-hide: detecteer scrollrichting en toggle data-hidden attribuut\n React.useEffect(() => {\n if (sticky !== 'auto-hide') return;\n\n let lastScrollY = window.scrollY;\n\n const handleScroll = () => {\n const currentScrollY = window.scrollY;\n const isScrollingDown =\n currentScrollY > lastScrollY && currentScrollY > 100;\n combinedRef.current?.setAttribute(\n 'data-hidden',\n String(isScrollingDown)\n );\n lastScrollY = currentScrollY;\n };\n\n window.addEventListener('scroll', handleScroll, { passive: true });\n return () => window.removeEventListener('scroll', handleScroll);\n }, [sticky, combinedRef]);\n\n // Drop-shadow: zet data-scrolled op \"true\" zodra de pagina gescrolled is.\n // Werkt voor zowel sticky als auto-hide — ongeacht scrollrichting.\n React.useEffect(() => {\n if (sticky === 'none') return;\n\n const updateScrolled = () => {\n combinedRef.current?.setAttribute(\n 'data-scrolled',\n String(window.scrollY > 0)\n );\n };\n\n // Direct bij mount instellen (pagina kan al gescrolled zijn)\n updateScrolled();\n\n window.addEventListener('scroll', updateScrolled, { passive: true });\n return () => window.removeEventListener('scroll', updateScrolled);\n }, [sticky, combinedRef]);\n\n // Focus management: bij openen zoekpaneel → focus naar input (klein of compact)\n React.useEffect(() => {\n if (isSearchOpen) {\n searchInputRef.current?.focus();\n compactSearchInputRef.current?.focus();\n }\n }, [isSearchOpen]);\n\n const handleMenuOpen = () => {\n setIsMenuOpen(true);\n onMenuOpen?.();\n };\n\n const handleMenuClose = () => {\n setIsMenuOpen(false);\n onMenuClose?.();\n // Focus terug naar menuknop\n menuButtonRef.current?.focus();\n };\n\n const handleSearchToggle = () => {\n const opening = !isSearchOpen;\n setIsSearchOpen(opening);\n if (opening) {\n onSearchOpen?.();\n } else {\n onSearchClose?.();\n // Focus terug naar zoek/sluit-knop — afhankelijk van actieve layout\n searchButtonRef.current?.focus();\n compactSearchButtonRef.current?.focus();\n }\n };\n\n const classes = classNames(\n 'dsn-page-header',\n sticky === 'sticky' && 'dsn-page-header--sticky',\n sticky === 'auto-hide' && 'dsn-page-header--auto-hide',\n layout === 'compact' && 'dsn-page-header--compact',\n colorScheme === 'inverse' && 'dsn-page-header--inverse',\n className\n );\n\n return (\n <>\n <header\n ref={combinedRef}\n className={classes}\n {...(sticky === 'auto-hide' ? { 'data-hidden': 'false' } : {})}\n {...props}\n >\n {/* ----------------------------------------------------------------\n Small viewport layout (verborgen boven 64em via CSS display:none)\n ---------------------------------------------------------------- */}\n <div className=\"dsn-page-header__small-layout\">\n <div className=\"dsn-page-header__inner\">\n {/* Inline-start: menuknop */}\n <div className=\"dsn-page-header__start\">\n {!hideMenuButton && (\n <Button\n ref={menuButtonRef}\n variant=\"subtle\"\n onClick={handleMenuOpen}\n iconStart={<Icon name=\"menu\" aria-hidden />}\n >\n {menuButtonLabel}\n {menuButtonBadgeLabel && (\n <span className=\"dsn-visually-hidden\">\n , {menuButtonBadgeLabel}\n </span>\n )}\n {menuButtonBadge}\n </Button>\n )}\n </div>\n\n {/* Gecentreerd logo */}\n <div className=\"dsn-page-header__logo\">{logoSlot}</div>\n\n {/* Inline-end: zoekknop / sluitknop */}\n <div className=\"dsn-page-header__end\">\n {!hideSearchButton && (\n <Button\n ref={searchButtonRef}\n variant=\"subtle\"\n aria-expanded={isSearchOpen}\n aria-controls={searchPanelId}\n onClick={handleSearchToggle}\n iconStart={\n <Icon name={isSearchOpen ? 'x' : 'search'} aria-hidden />\n }\n >\n {isSearchOpen ? closeButtonLabel : searchButtonLabel}\n </Button>\n )}\n </div>\n </div>\n\n {/* Zoekpaneel */}\n <div\n id={searchPanelId}\n className=\"dsn-page-header__search-panel\"\n hidden={!isSearchOpen}\n >\n <div className=\"dsn-page-header__search-inner\">\n <SearchInput\n ref={searchInputRef}\n placeholder={searchInputPlaceholder}\n aria-label={searchInputAriaLabel}\n />\n <Button variant=\"strong\">{searchSubmitLabel}</Button>\n </div>\n </div>\n </div>\n\n {/* ----------------------------------------------------------------\n Large viewport layout (zichtbaar boven 64em, alleen bij layout=\"default\")\n ---------------------------------------------------------------- */}\n {layout === 'default' && (\n <div className=\"dsn-page-header__large-layout\">\n {/* Masthead: neutrale achtergrond — logo + servicemenu + zoek */}\n <div className=\"dsn-page-header__masthead\">\n <div className=\"dsn-page-header__masthead-inner\">\n <div className=\"dsn-page-header__logo\">{logoSlot}</div>\n\n <div className=\"dsn-page-header__secondary-nav\">\n {(secondaryNavigationLarge ?? secondaryNavigation) && (\n <nav aria-label={secondaryNavAriaLabel}>\n {secondaryNavigationLarge ?? secondaryNavigation}\n </nav>\n )}\n {searchSlot && (\n <div className=\"dsn-page-header__searchbox\">\n {searchSlot}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Navigatiebalk: accent-1 achtergrond — primaire navigatie (large viewport) */}\n <div className=\"dsn-page-header__navbar\">\n <div className=\"dsn-page-header__navbar-inner\">\n {(primaryNavigationLarge ?? primaryNavigation) && (\n <nav aria-label={primaryNavAriaLabel}>\n {primaryNavigationLarge ?? primaryNavigation}\n </nav>\n )}\n </div>\n </div>\n </div>\n )}\n\n {/* ----------------------------------------------------------------\n Compact layout (zichtbaar boven 64em wanneer layout=\"compact\")\n Eén rij: logo (1fr) | primaire navigatie (auto) | servicemenu + zoek (1fr)\n ---------------------------------------------------------------- */}\n {layout === 'compact' && (\n <div className=\"dsn-page-header__compact-layout\">\n <div className=\"dsn-page-header__compact-inner\">\n {/* Logo — inline-start (eerste gridkolom) */}\n <div className=\"dsn-page-header__logo\">{logoSlot}</div>\n\n {/* Primaire navigatie — gecentreerd (middelste gridkolom)\n Gebruikt primaryNavigationLarge als aanwezig, anders primaryNavigation.\n Dit garandeert dat de Drawer altijd de verticale variant ontvangt. */}\n <div className=\"dsn-page-header__compact-primary-nav\">\n {(primaryNavigationLarge ?? primaryNavigation) && (\n <nav aria-label={primaryNavAriaLabel}>\n {primaryNavigationLarge ?? primaryNavigation}\n </nav>\n )}\n </div>\n\n {/* Servicemenu + zoekknop (icon-only) — inline-end (derde gridkolom) */}\n <div className=\"dsn-page-header__compact-secondary\">\n {(secondaryNavigationLarge ?? secondaryNavigation) && (\n <nav aria-label={secondaryNavAriaLabel}>\n {secondaryNavigationLarge ?? secondaryNavigation}\n </nav>\n )}\n {!hideSearchButton && (\n <Button\n ref={compactSearchButtonRef}\n variant=\"subtle\"\n iconOnly\n aria-expanded={isSearchOpen}\n aria-controls={compactSearchPanelId}\n onClick={handleSearchToggle}\n iconStart={\n <Icon\n name={isSearchOpen ? 'x' : 'search'}\n aria-hidden\n />\n }\n >\n {isSearchOpen ? closeButtonLabel : searchButtonLabel}\n </Button>\n )}\n </div>\n </div>\n\n {/* Zoekpaneel compact layout */}\n <div\n id={compactSearchPanelId}\n className=\"dsn-page-header__search-panel\"\n hidden={!isSearchOpen}\n >\n <div className=\"dsn-page-header__search-inner\">\n <SearchInput\n ref={compactSearchInputRef}\n placeholder={searchInputPlaceholder}\n aria-label={searchInputAriaLabel}\n />\n <Button variant=\"strong\">{searchSubmitLabel}</Button>\n </div>\n </div>\n </div>\n )}\n </header>\n\n {/* Navigatielade (sibling aan PageHeader, altijd in DOM) */}\n <Drawer isOpen={isMenuOpen} onClose={handleMenuClose} side=\"left\">\n <DrawerHeader>\n <DrawerHeading>{menuButtonLabel}</DrawerHeading>\n </DrawerHeader>\n <DrawerBody>\n <Stack space=\"5xl\">\n {primaryNavigation && (\n <nav aria-label={primaryNavAriaLabel}>{primaryNavigation}</nav>\n )}\n {secondaryNavigation && (\n <nav aria-label={secondaryNavAriaLabel}>\n {secondaryNavigation}\n </nav>\n )}\n </Stack>\n </DrawerBody>\n </Drawer>\n </>\n );\n }\n);\n\nPageHeader.displayName = 'PageHeader';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PageHeader2.mjs","names":[],"sources":["../../src/PageHeader/PageHeader.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames } from '@dsn-starter-kit/core';\nimport { Button } from '../Button';\nimport { Icon } from '../Icon';\nimport { SearchInput } from '../SearchInput';\nimport { Drawer, DrawerBody, DrawerHeader, DrawerHeading } from '../Drawer';\nimport { Stack } from '../Stack';\nimport './PageHeader.css';\n\nexport type PageHeaderSticky = 'none' | 'sticky' | 'auto-hide';\n\n/** Auto-hide: boven deze scrollpositie (px) blijft de header altijd zichtbaar */\nconst AUTO_HIDE_OFFSET = 100;\n\n/** Auto-hide: zoveel px omhoog scrollen voordat de header terugkomt */\nconst AUTO_HIDE_REVEAL_DISTANCE = 64;\nexport type PageHeaderLayout = 'default' | 'compact';\nexport type PageHeaderColorScheme = 'default' | 'inverse';\n\nexport interface PageHeaderProps extends Omit<\n React.HTMLAttributes<HTMLElement>,\n 'children'\n> {\n /**\n * Logo-inhoud — `<svg>`, `<img>`, of een `<a>` die een logo omhult.\n * De CSS past automatisch `max-block-size` toe op de directe child.\n */\n logoSlot: React.ReactNode;\n\n /**\n * Scrollgedrag van de header.\n * - `none` (standaard): header scrollt mee met de pagina\n * - `sticky`: header blijft bovenaan de viewport vastgeplakt\n * - `auto-hide`: sticky + verbergt bij scroll-down, toont bij scroll-up\n * @default 'none'\n */\n sticky?: PageHeaderSticky;\n\n /**\n * Lay-out van de header op large viewport (≥ 64em).\n * - `default`: twee horizontale banden — Masthead (logo + servicemenu + zoekveld)\n * en Navigatiebalk (primaire navigatie op accent-1 achtergrond)\n * - `compact`: één enkele rij — logo (inline-start), primaire navigatie (gecentreerd),\n * servicemenu + zoekknop (inline-end). Geeft `primaryNavigationLarge` voorrang\n * boven `primaryNavigation` (en idem voor secondary) zodat de Drawer altijd\n * de verticale variant ontvangt.\n * @default 'default'\n */\n layout?: PageHeaderLayout;\n\n /**\n * Kleurschema van de header.\n * - `default`: neutrale achtergrond met accent-1 navbar\n * - `inverse`: sterke accent-1-inverse achtergrond op navbar en compact balk\n * voor prominente branding. Het masthead blijft altijd neutraal.\n * Logo-kleuren passen zich automatisch aan via CSS context overrides.\n * @default 'default'\n */\n colorScheme?: PageHeaderColorScheme;\n\n /**\n * Initiële open-staat van het zoekpaneel (small viewport).\n * Handig voor Storybook en tests — het paneel kan daarna nog steeds\n * worden geopend/gesloten via de knop.\n * @default false\n */\n initialSearchOpen?: boolean;\n\n /**\n * Primaire navigatie-inhoud in de Drawer (small viewport) — doorgaans een verticale `<Menu>` met\n * `<MenuLink>`-items inclusief uitklapmogelijkheden voor sub-niveaus.\n */\n primaryNavigation?: React.ReactNode;\n\n /**\n * Primaire navigatie-inhoud in de Navigatiebalk (large viewport) — doorgaans een horizontale\n * `<Menu>` met alleen Level 1 `<MenuLink>`-items. Als niet meegegeven valt de component\n * terug op `primaryNavigation`.\n */\n primaryNavigationLarge?: React.ReactNode;\n\n /**\n * Servicemenu-inhoud in de Drawer (small viewport) — doorgaans een verticale `<Menu>`.\n */\n secondaryNavigation?: React.ReactNode;\n\n /**\n * Servicemenu-inhoud in de Masthead (large viewport) — doorgaans een horizontale `<Menu>`.\n * Als niet meegegeven valt de component terug op `secondaryNavigation`.\n */\n secondaryNavigationLarge?: React.ReactNode;\n\n /**\n * Inline zoekveld voor de Masthead op large viewport (SearchInput + zoekknop).\n * Optioneel — toont geen zoekveld als weggelaten.\n */\n searchSlot?: React.ReactNode;\n\n /**\n * Visuele badge-indicator bij de menuknop (small viewport), doorgaans een `<DotBadge>`.\n * Gebruik dit om ongelezen meldingen te signaleren. De badge is altijd `aria-hidden` —\n * geef de toegankelijke tekst mee via `menuButtonBadgeLabel`.\n */\n menuButtonBadge?: React.ReactNode;\n\n /**\n * Toegankelijke tekst die wordt toegevoegd aan het label van de menuknop als er een badge\n * aanwezig is, bijvoorbeeld `\"2 nieuwe berichten\"`. Wordt visueel verborgen getoond zodat\n * screenreadergebruikers de melding horen: \"Menu, 2 nieuwe berichten\".\n * Vereist als `menuButtonBadge` is meegegeven.\n */\n menuButtonBadgeLabel?: string;\n\n /**\n * Callback wanneer de navigatielade opent.\n */\n onMenuOpen?: () => void;\n\n /**\n * Callback wanneer de navigatielade sluit.\n */\n onMenuClose?: () => void;\n\n /**\n * Callback wanneer het zoekpaneel opent.\n */\n onSearchOpen?: () => void;\n\n /**\n * Callback wanneer het zoekpaneel sluit.\n */\n onSearchClose?: () => void;\n\n // ── i18n labels ────────────────────────────────────────────────────────────\n\n /**\n * Label van de menuknop en de Drawer-heading.\n * @default 'Menu'\n */\n menuButtonLabel?: string;\n\n /**\n * Label van de zoekknop wanneer het zoekpaneel gesloten is.\n * @default 'Zoeken'\n */\n searchButtonLabel?: string;\n\n /**\n * Label van de zoekknop wanneer het zoekpaneel open is.\n * @default 'Sluiten'\n */\n closeButtonLabel?: string;\n\n /**\n * Placeholder van het zoekveld in het zoekpaneel (small viewport en compact layout).\n * @default 'Zoeken…'\n */\n searchInputPlaceholder?: string;\n\n /**\n * `aria-label` van het zoekveld in het zoekpaneel.\n * @default 'Zoekopdracht'\n */\n searchInputAriaLabel?: string;\n\n /**\n * Label van de zoek-submitknop in het zoekpaneel.\n * @default 'Zoeken'\n */\n searchSubmitLabel?: string;\n\n /**\n * `aria-label` van de primaire navigatie-`<nav>` (large viewport) en\n * visueel verborgen heading in de Drawer.\n * @default 'Hoofd-navigatie'\n */\n primaryNavAriaLabel?: string;\n\n /**\n * `aria-label` van het servicemenu-`<nav>` (large viewport) en\n * visueel verborgen heading in de Drawer.\n * @default 'Service-navigatie'\n */\n secondaryNavAriaLabel?: string;\n\n /**\n * Verbergt de menuknop in de small viewport layout.\n * Gebruik dit wanneer er geen navigatie aanwezig is (bijv. formulierpagina's).\n * @default false\n */\n hideMenuButton?: boolean;\n\n /**\n * Verbergt de zoekknop in zowel de small viewport als compact layout.\n * Gebruik dit wanneer zoeken niet relevant is (bijv. formulierpagina's).\n * @default false\n */\n hideSearchButton?: boolean;\n\n className?: string;\n}\n\n/**\n * PageHeader component\n * Primaire navigatieheader voor een pagina. Mobile-first implementatie.\n *\n * Op mobile toont de header drie elementen:\n * - Menuknop (inline-start) — opent een `Drawer` met primaire en service-navigatie\n * - Logo (gecentreerd, onafhankelijk van knopbreedte via CSS-grid 1fr auto 1fr)\n * - Zoekknop (inline-end) — opent een zoekpaneel direct onder de header\n *\n * @example\n * ```tsx\n * <PageHeader\n * logoSlot={\n * <a href=\"/\">\n * <Logo aria-hidden={true} />\n * <span className=\"dsn-visually-hidden\">Starter Kit — terug naar homepage</span>\n * </a>\n * }\n * primaryNavigation={\n * <Menu orientation=\"vertical\">\n * <MenuLink href=\"/home\" level={1}>Home</MenuLink>\n * <MenuLink href=\"/over\" level={1}>Over ons</MenuLink>\n * </Menu>\n * }\n * secondaryNavigation={\n * <Menu orientation=\"vertical\">\n * <MenuLink href=\"/contact\" level={1}>Contact</MenuLink>\n * </Menu>\n * }\n * />\n * ```\n */\nexport const PageHeader = React.forwardRef<HTMLElement, PageHeaderProps>(\n (\n {\n className,\n logoSlot,\n sticky = 'none',\n layout = 'default',\n colorScheme = 'default',\n initialSearchOpen = false,\n primaryNavigation,\n primaryNavigationLarge,\n secondaryNavigation,\n secondaryNavigationLarge,\n searchSlot,\n menuButtonBadge,\n menuButtonBadgeLabel,\n onMenuOpen,\n onMenuClose,\n onSearchOpen,\n onSearchClose,\n menuButtonLabel = 'Menu',\n searchButtonLabel = 'Zoeken',\n closeButtonLabel = 'Sluiten',\n searchInputPlaceholder = 'Zoeken…',\n searchInputAriaLabel = 'Zoekopdracht',\n searchSubmitLabel = 'Zoeken',\n primaryNavAriaLabel = 'Hoofd-navigatie',\n secondaryNavAriaLabel = 'Service-navigatie',\n hideMenuButton = false,\n hideSearchButton = false,\n ...props\n },\n ref\n ) => {\n const [isMenuOpen, setIsMenuOpen] = React.useState(false);\n const [isSearchOpen, setIsSearchOpen] = React.useState(initialSearchOpen);\n\n const headerRef = React.useRef<HTMLElement>(null);\n const combinedRef = (ref as React.RefObject<HTMLElement>) ?? headerRef;\n\n const menuButtonRef = React.useRef<HTMLButtonElement>(null);\n const searchButtonRef = React.useRef<HTMLButtonElement>(null);\n const searchInputRef = React.useRef<HTMLInputElement>(null);\n const compactSearchButtonRef = React.useRef<HTMLButtonElement>(null);\n const compactSearchInputRef = React.useRef<HTMLInputElement>(null);\n\n const searchPanelId = React.useId();\n const compactSearchPanelId = React.useId();\n\n // Auto-hide: detecteer scrollrichting en toggle data-hidden attribuut\n React.useEffect(() => {\n if (sticky !== 'auto-hide') return;\n\n let lastScrollY = window.scrollY;\n // Afgelegde afstand omhoog sinds de laatste scroll-down. De header komt\n // pas terug na AUTO_HIDE_REVEAL_DISTANCE, zodat een kleine beweging\n // omhoog (of een terugverende swipe) hem niet direct in beeld schuift.\n let scrolledUp = 0;\n\n const handleScroll = () => {\n const currentScrollY = window.scrollY;\n const delta = currentScrollY - lastScrollY;\n lastScrollY = currentScrollY;\n\n let hidden: boolean;\n if (currentScrollY <= AUTO_HIDE_OFFSET) {\n hidden = false;\n scrolledUp = 0;\n } else if (delta > 0) {\n hidden = true;\n scrolledUp = 0;\n } else if (delta < 0) {\n scrolledUp -= delta;\n if (scrolledUp < AUTO_HIDE_REVEAL_DISTANCE) return;\n hidden = false;\n } else {\n return;\n }\n\n combinedRef.current?.setAttribute('data-hidden', String(hidden));\n };\n\n window.addEventListener('scroll', handleScroll, { passive: true });\n return () => window.removeEventListener('scroll', handleScroll);\n }, [sticky, combinedRef]);\n\n // Drop-shadow: zet data-scrolled op \"true\" zodra de pagina gescrolled is.\n // Werkt voor zowel sticky als auto-hide — ongeacht scrollrichting.\n React.useEffect(() => {\n if (sticky === 'none') return;\n\n const updateScrolled = () => {\n combinedRef.current?.setAttribute(\n 'data-scrolled',\n String(window.scrollY > 0)\n );\n };\n\n // Direct bij mount instellen (pagina kan al gescrolled zijn)\n updateScrolled();\n\n window.addEventListener('scroll', updateScrolled, { passive: true });\n return () => window.removeEventListener('scroll', updateScrolled);\n }, [sticky, combinedRef]);\n\n // Focus management: bij openen zoekpaneel → focus naar input (klein of compact)\n React.useEffect(() => {\n if (isSearchOpen) {\n searchInputRef.current?.focus();\n compactSearchInputRef.current?.focus();\n }\n }, [isSearchOpen]);\n\n const handleMenuOpen = () => {\n setIsMenuOpen(true);\n onMenuOpen?.();\n };\n\n const handleMenuClose = () => {\n setIsMenuOpen(false);\n onMenuClose?.();\n // Focus terug naar menuknop\n menuButtonRef.current?.focus();\n };\n\n const handleSearchToggle = () => {\n const opening = !isSearchOpen;\n setIsSearchOpen(opening);\n if (opening) {\n onSearchOpen?.();\n } else {\n onSearchClose?.();\n // Focus terug naar zoek/sluit-knop — afhankelijk van actieve layout\n searchButtonRef.current?.focus();\n compactSearchButtonRef.current?.focus();\n }\n };\n\n const classes = classNames(\n 'dsn-page-header',\n sticky === 'sticky' && 'dsn-page-header--sticky',\n sticky === 'auto-hide' && 'dsn-page-header--auto-hide',\n layout === 'compact' && 'dsn-page-header--compact',\n colorScheme === 'inverse' && 'dsn-page-header--inverse',\n className\n );\n\n return (\n <>\n <header\n ref={combinedRef}\n className={classes}\n {...(sticky === 'auto-hide' ? { 'data-hidden': 'false' } : {})}\n {...props}\n >\n {/* ----------------------------------------------------------------\n Small viewport layout (verborgen boven 64em via CSS display:none)\n ---------------------------------------------------------------- */}\n <div className=\"dsn-page-header__small-layout\">\n <div className=\"dsn-page-header__inner\">\n {/* Inline-start: menuknop */}\n <div className=\"dsn-page-header__start\">\n {!hideMenuButton && (\n <Button\n ref={menuButtonRef}\n variant=\"subtle\"\n onClick={handleMenuOpen}\n iconStart={<Icon name=\"menu\" aria-hidden />}\n >\n {menuButtonLabel}\n {menuButtonBadgeLabel && (\n <span className=\"dsn-visually-hidden\">\n , {menuButtonBadgeLabel}\n </span>\n )}\n {menuButtonBadge}\n </Button>\n )}\n </div>\n\n {/* Gecentreerd logo */}\n <div className=\"dsn-page-header__logo\">{logoSlot}</div>\n\n {/* Inline-end: zoekknop / sluitknop */}\n <div className=\"dsn-page-header__end\">\n {!hideSearchButton && (\n <Button\n ref={searchButtonRef}\n variant=\"subtle\"\n aria-expanded={isSearchOpen}\n aria-controls={searchPanelId}\n onClick={handleSearchToggle}\n iconStart={\n <Icon name={isSearchOpen ? 'x' : 'search'} aria-hidden />\n }\n >\n {isSearchOpen ? closeButtonLabel : searchButtonLabel}\n </Button>\n )}\n </div>\n </div>\n\n {/* Zoekpaneel */}\n <div\n id={searchPanelId}\n className=\"dsn-page-header__search-panel\"\n hidden={!isSearchOpen}\n >\n <div className=\"dsn-page-header__search-inner\">\n <SearchInput\n ref={searchInputRef}\n placeholder={searchInputPlaceholder}\n aria-label={searchInputAriaLabel}\n />\n <Button variant=\"strong\">{searchSubmitLabel}</Button>\n </div>\n </div>\n </div>\n\n {/* ----------------------------------------------------------------\n Large viewport layout (zichtbaar boven 64em, alleen bij layout=\"default\")\n ---------------------------------------------------------------- */}\n {layout === 'default' && (\n <div className=\"dsn-page-header__large-layout\">\n {/* Masthead: neutrale achtergrond — logo + servicemenu + zoek */}\n <div className=\"dsn-page-header__masthead\">\n <div className=\"dsn-page-header__masthead-inner\">\n <div className=\"dsn-page-header__logo\">{logoSlot}</div>\n\n <div className=\"dsn-page-header__secondary-nav\">\n {(secondaryNavigationLarge ?? secondaryNavigation) && (\n <nav aria-label={secondaryNavAriaLabel}>\n {secondaryNavigationLarge ?? secondaryNavigation}\n </nav>\n )}\n {searchSlot && (\n <div className=\"dsn-page-header__searchbox\">\n {searchSlot}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Navigatiebalk: accent-1 achtergrond — primaire navigatie (large viewport) */}\n <div className=\"dsn-page-header__navbar\">\n <div className=\"dsn-page-header__navbar-inner\">\n {(primaryNavigationLarge ?? primaryNavigation) && (\n <nav aria-label={primaryNavAriaLabel}>\n {primaryNavigationLarge ?? primaryNavigation}\n </nav>\n )}\n </div>\n </div>\n </div>\n )}\n\n {/* ----------------------------------------------------------------\n Compact layout (zichtbaar boven 64em wanneer layout=\"compact\")\n Eén rij: logo (1fr) | primaire navigatie (auto) | servicemenu + zoek (1fr)\n ---------------------------------------------------------------- */}\n {layout === 'compact' && (\n <div className=\"dsn-page-header__compact-layout\">\n <div className=\"dsn-page-header__compact-inner\">\n {/* Logo — inline-start (eerste gridkolom) */}\n <div className=\"dsn-page-header__logo\">{logoSlot}</div>\n\n {/* Primaire navigatie — gecentreerd (middelste gridkolom)\n Gebruikt primaryNavigationLarge als aanwezig, anders primaryNavigation.\n Dit garandeert dat de Drawer altijd de verticale variant ontvangt. */}\n <div className=\"dsn-page-header__compact-primary-nav\">\n {(primaryNavigationLarge ?? primaryNavigation) && (\n <nav aria-label={primaryNavAriaLabel}>\n {primaryNavigationLarge ?? primaryNavigation}\n </nav>\n )}\n </div>\n\n {/* Servicemenu + zoekknop (icon-only) — inline-end (derde gridkolom) */}\n <div className=\"dsn-page-header__compact-secondary\">\n {(secondaryNavigationLarge ?? secondaryNavigation) && (\n <nav aria-label={secondaryNavAriaLabel}>\n {secondaryNavigationLarge ?? secondaryNavigation}\n </nav>\n )}\n {!hideSearchButton && (\n <Button\n ref={compactSearchButtonRef}\n variant=\"subtle\"\n iconOnly\n aria-expanded={isSearchOpen}\n aria-controls={compactSearchPanelId}\n onClick={handleSearchToggle}\n iconStart={\n <Icon\n name={isSearchOpen ? 'x' : 'search'}\n aria-hidden\n />\n }\n >\n {isSearchOpen ? closeButtonLabel : searchButtonLabel}\n </Button>\n )}\n </div>\n </div>\n\n {/* Zoekpaneel compact layout */}\n <div\n id={compactSearchPanelId}\n className=\"dsn-page-header__search-panel\"\n hidden={!isSearchOpen}\n >\n <div className=\"dsn-page-header__search-inner\">\n <SearchInput\n ref={compactSearchInputRef}\n placeholder={searchInputPlaceholder}\n aria-label={searchInputAriaLabel}\n />\n <Button variant=\"strong\">{searchSubmitLabel}</Button>\n </div>\n </div>\n </div>\n )}\n </header>\n\n {/* Navigatielade (sibling aan PageHeader, altijd in DOM) */}\n <Drawer\n isOpen={isMenuOpen}\n onClose={handleMenuClose}\n side=\"left\"\n triggerRef={menuButtonRef}\n >\n <DrawerHeader>\n <DrawerHeading>{menuButtonLabel}</DrawerHeading>\n </DrawerHeader>\n <DrawerBody>\n <Stack space=\"5xl\">\n {primaryNavigation && (\n <nav aria-label={primaryNavAriaLabel}>{primaryNavigation}</nav>\n )}\n {secondaryNavigation && (\n <nav aria-label={secondaryNavAriaLabel}>\n {secondaryNavigation}\n </nav>\n )}\n </Stack>\n </DrawerBody>\n </Drawer>\n </>\n );\n }\n);\n\nPageHeader.displayName = 'PageHeader';\n"],"mappings":"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"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { FormControlInlineSize } from "@dsn-starter-kit/core";
|
|
3
3
|
//#region src/PasswordInput/PasswordInput.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Inline-size variants offered by PasswordInput. xs and sm are left out: they
|
|
6
|
+
* are too narrow for the content this field is meant for.
|
|
7
|
+
*/
|
|
8
|
+
type PasswordInputInlineSize = Exclude<FormControlInlineSize, 'xs' | 'sm'>;
|
|
4
9
|
type PasswordAutocomplete = 'current-password' | 'new-password' | 'off';
|
|
5
10
|
interface PasswordInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'> {
|
|
6
11
|
/**
|
|
@@ -17,10 +22,10 @@ interface PasswordInputProps extends Omit<React.InputHTMLAttributes<HTMLInputEle
|
|
|
17
22
|
*/
|
|
18
23
|
invalid?: boolean;
|
|
19
24
|
/**
|
|
20
|
-
*
|
|
21
|
-
* @default undefined (uses default max-
|
|
25
|
+
* Inline-size variant for the input (md, lg, xl or full)
|
|
26
|
+
* @default undefined (uses default max-inline-size from form-control)
|
|
22
27
|
*/
|
|
23
|
-
|
|
28
|
+
inlineSize?: PasswordInputInlineSize;
|
|
24
29
|
/**
|
|
25
30
|
* Additional CSS class names
|
|
26
31
|
*/
|
|
@@ -50,5 +55,5 @@ interface PasswordInputProps extends Omit<React.InputHTMLAttributes<HTMLInputEle
|
|
|
50
55
|
*/
|
|
51
56
|
declare const PasswordInput: React.ForwardRefExoticComponent<PasswordInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
52
57
|
//#endregion
|
|
53
|
-
export { PasswordAutocomplete, PasswordInput, PasswordInputProps };
|
|
58
|
+
export { PasswordAutocomplete, PasswordInput, PasswordInputInlineSize, PasswordInputProps };
|
|
54
59
|
//# sourceMappingURL=PasswordInput.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PasswordInput.d.mts","names":[],"sources":["../../src/PasswordInput/PasswordInput.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"PasswordInput.d.mts","names":[],"sources":["../../src/PasswordInput/PasswordInput.tsx"],"mappings":";;;;;;;KAQY,0BAA0B,QACpC;KAIU;UAEK,2BAA2B,KAC1C,MAAM,oBAAoB;;;;;;;;EAU1B,uBAAuB;;;;;EAMvB;;;;;EAMA,aAAa;;;;EAKb;;;;;;;;;;;;;;;;;;;;;;;;cAyBW,eAAa,MAAA,0BAAA,qBAAA,MAAA,cAAA"}
|
|
@@ -25,8 +25,8 @@ import { jsx } from "react/jsx-runtime";
|
|
|
25
25
|
* <PasswordInput invalid aria-invalid="true" aria-describedby="error" />
|
|
26
26
|
* ```
|
|
27
27
|
*/
|
|
28
|
-
const PasswordInput = React.forwardRef(({ passwordAutocomplete = "current-password", className, invalid,
|
|
29
|
-
const classes = classNames("dsn-text-input",
|
|
28
|
+
const PasswordInput = React.forwardRef(({ passwordAutocomplete = "current-password", className, invalid, inlineSize, autoComplete, ...props }, ref) => {
|
|
29
|
+
const classes = classNames("dsn-text-input", inlineSize && `dsn-text-input--inline-size-${inlineSize}`, className);
|
|
30
30
|
return /* @__PURE__ */ jsx("input", {
|
|
31
31
|
ref,
|
|
32
32
|
type: "password",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PasswordInput2.mjs","names":[],"sources":["../../src/PasswordInput/PasswordInput.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames,
|
|
1
|
+
{"version":3,"file":"PasswordInput2.mjs","names":[],"sources":["../../src/PasswordInput/PasswordInput.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames, FormControlInlineSize } from '@dsn-starter-kit/core';\nimport './PasswordInput.css';\n\n/**\n * Inline-size variants offered by PasswordInput. xs and sm are left out: they\n * are too narrow for the content this field is meant for.\n */\nexport type PasswordInputInlineSize = Exclude<\n FormControlInlineSize,\n 'xs' | 'sm'\n>;\n\nexport type PasswordAutocomplete = 'current-password' | 'new-password' | 'off';\n\nexport interface PasswordInputProps extends Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'type'\n> {\n /**\n * Autocomplete hint for password managers\n * - 'current-password': voor inlogformulieren (default)\n * - 'new-password': voor registratie- en wachtwoord wijzigformulieren\n * - 'off': autocomplete uitschakelen\n * @default 'current-password'\n */\n passwordAutocomplete?: PasswordAutocomplete;\n\n /**\n * Whether the input is in an invalid state\n * @default false\n */\n invalid?: boolean;\n\n /**\n * Inline-size variant for the input (md, lg, xl or full)\n * @default undefined (uses default max-inline-size from form-control)\n */\n inlineSize?: PasswordInputInlineSize;\n\n /**\n * Additional CSS class names\n */\n className?: string;\n}\n\n/**\n * Password Input component\n * Uses type=\"password\" for secure text entry.\n * Het tonen/verbergen van het wachtwoord is bewust niet ingebouwd in dit component —\n * dat patroon wordt separaat gedefinieerd via een Button naast het invoerveld.\n *\n * @example\n * ```tsx\n * // Login form (current password)\n * <PasswordInput placeholder=\"Wachtwoord\" />\n *\n * // Registration form (new password)\n * <PasswordInput passwordAutocomplete=\"new-password\" placeholder=\"Nieuw wachtwoord\" />\n *\n * // With label\n * <FormFieldLabel htmlFor=\"password\">Wachtwoord</FormFieldLabel>\n * <PasswordInput id=\"password\" />\n *\n * // Invalid state\n * <PasswordInput invalid aria-invalid=\"true\" aria-describedby=\"error\" />\n * ```\n */\nexport const PasswordInput = React.forwardRef<\n HTMLInputElement,\n PasswordInputProps\n>(\n (\n {\n passwordAutocomplete = 'current-password',\n className,\n invalid,\n inlineSize,\n autoComplete,\n ...props\n },\n ref\n ) => {\n const classes = classNames(\n 'dsn-text-input',\n inlineSize && `dsn-text-input--inline-size-${inlineSize}`,\n className\n );\n\n return (\n <input\n ref={ref}\n type=\"password\"\n className={classes}\n autoComplete={autoComplete || passwordAutocomplete}\n aria-invalid={invalid || undefined}\n {...props}\n />\n );\n }\n);\n\nPasswordInput.displayName = 'PasswordInput';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAoEA,MAAa,gBAAgB,MAAM,YAK/B,EACE,uBAAuB,oBACvB,WACA,SACA,YACA,cACA,GAAG,SAEL,QACG;CACH,MAAM,UAAU,WACd,kBACA,cAAc,+BAA+B,cAC7C,SACF;CAEA,OACE,oBAAC,SAAD;EACO;EACL,MAAK;EACL,WAAW;EACX,cAAc,gBAAgB;EAC9B,gBAAc,WAAW,KAAA;EACzB,GAAI;CACL,CAAA;AAEL,CACF;AAEA,cAAc,cAAc"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { FormControlInlineSize } from "@dsn-starter-kit/core";
|
|
3
3
|
//#region src/SearchInput/SearchInput.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Inline-size variants offered by SearchInput. xs and sm are left out: they
|
|
6
|
+
* are too narrow for the content this field is meant for.
|
|
7
|
+
*/
|
|
8
|
+
type SearchInputInlineSize = Exclude<FormControlInlineSize, 'xs' | 'sm'>;
|
|
4
9
|
interface SearchInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'> {
|
|
5
10
|
/**
|
|
6
11
|
* Whether the input is in an invalid state
|
|
@@ -8,10 +13,10 @@ interface SearchInputProps extends Omit<React.InputHTMLAttributes<HTMLInputEleme
|
|
|
8
13
|
*/
|
|
9
14
|
invalid?: boolean;
|
|
10
15
|
/**
|
|
11
|
-
*
|
|
12
|
-
* @default undefined (uses default max-
|
|
16
|
+
* Inline-size variant for the input (md, lg, xl or full)
|
|
17
|
+
* @default undefined (uses default max-inline-size from form-control)
|
|
13
18
|
*/
|
|
14
|
-
|
|
19
|
+
inlineSize?: SearchInputInlineSize;
|
|
15
20
|
/**
|
|
16
21
|
* Additional CSS class names
|
|
17
22
|
*/
|
|
@@ -37,5 +42,5 @@ interface SearchInputProps extends Omit<React.InputHTMLAttributes<HTMLInputEleme
|
|
|
37
42
|
*/
|
|
38
43
|
declare const SearchInput: React.ForwardRefExoticComponent<SearchInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
39
44
|
//#endregion
|
|
40
|
-
export { SearchInput, SearchInputProps };
|
|
45
|
+
export { SearchInput, SearchInputInlineSize, SearchInputProps };
|
|
41
46
|
//# sourceMappingURL=SearchInput.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchInput.d.mts","names":[],"sources":["../../src/SearchInput/SearchInput.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"SearchInput.d.mts","names":[],"sources":["../../src/SearchInput/SearchInput.tsx"],"mappings":";;;;;;;KASY,wBAAwB,QAAQ;UAE3B,yBAAyB,KACxC,MAAM,oBAAoB;;;;;EAO1B;;;;;EAMA,aAAa;;;;EAKb;;;;;;;;;;;;;;;;;;;;cAqBW,aAAW,MAAA,0BAAA,mBAAA,MAAA,cAAA"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Icon } from "../Icon/Icon2.mjs";
|
|
2
|
-
/* empty css */
|
|
3
2
|
/* empty css */
|
|
4
3
|
import React from "react";
|
|
5
4
|
import { classNames } from "@dsn-starter-kit/core";
|
|
@@ -23,8 +22,8 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
23
22
|
* <SearchInput invalid aria-invalid="true" aria-describedby="error" />
|
|
24
23
|
* ```
|
|
25
24
|
*/
|
|
26
|
-
const SearchInput = React.forwardRef(({ className, invalid,
|
|
27
|
-
const wrapperClasses = classNames("dsn-search-input-wrapper",
|
|
25
|
+
const SearchInput = React.forwardRef(({ className, invalid, inlineSize, ...props }, ref) => {
|
|
26
|
+
const wrapperClasses = classNames("dsn-search-input-wrapper", inlineSize && `dsn-search-input-wrapper--inline-size-${inlineSize}`);
|
|
28
27
|
const inputClasses = classNames("dsn-text-input", "dsn-search-input", className);
|
|
29
28
|
return /* @__PURE__ */ jsxs("div", {
|
|
30
29
|
className: wrapperClasses,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchInput2.mjs","names":[],"sources":["../../src/SearchInput/SearchInput.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames,
|
|
1
|
+
{"version":3,"file":"SearchInput2.mjs","names":[],"sources":["../../src/SearchInput/SearchInput.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames, FormControlInlineSize } from '@dsn-starter-kit/core';\nimport { Icon } from '../Icon';\nimport './SearchInput.css';\n\n/**\n * Inline-size variants offered by SearchInput. xs and sm are left out: they\n * are too narrow for the content this field is meant for.\n */\nexport type SearchInputInlineSize = Exclude<FormControlInlineSize, 'xs' | 'sm'>;\n\nexport interface SearchInputProps extends Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'type'\n> {\n /**\n * Whether the input is in an invalid state\n * @default false\n */\n invalid?: boolean;\n\n /**\n * Inline-size variant for the input (md, lg, xl or full)\n * @default undefined (uses default max-inline-size from form-control)\n */\n inlineSize?: SearchInputInlineSize;\n\n /**\n * Additional CSS class names\n */\n className?: string;\n}\n\n/**\n * Search Input component\n * Search input with a non-interactive search icon positioned at inline-start.\n * The icon has the same color as the input text (dsn-text-input-color).\n *\n * @example\n * ```tsx\n * // Basic usage\n * <SearchInput placeholder=\"Zoeken...\" />\n *\n * // With label\n * <FormFieldLabel htmlFor=\"search\">Zoeken</FormFieldLabel>\n * <SearchInput id=\"search\" />\n *\n * // Invalid state\n * <SearchInput invalid aria-invalid=\"true\" aria-describedby=\"error\" />\n * ```\n */\nexport const SearchInput = React.forwardRef<HTMLInputElement, SearchInputProps>(\n ({ className, invalid, inlineSize, ...props }, ref) => {\n const wrapperClasses = classNames(\n 'dsn-search-input-wrapper',\n inlineSize && `dsn-search-input-wrapper--inline-size-${inlineSize}`\n );\n const inputClasses = classNames(\n 'dsn-text-input',\n 'dsn-search-input',\n className\n );\n\n return (\n <div className={wrapperClasses}>\n <Icon name=\"search\" className=\"dsn-search-input__icon\" aria-hidden />\n <input\n ref={ref}\n type=\"search\"\n className={inputClasses}\n aria-invalid={invalid || undefined}\n {...props}\n />\n </div>\n );\n }\n);\n\nSearchInput.displayName = 'SearchInput';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAmDA,MAAa,cAAc,MAAM,YAC9B,EAAE,WAAW,SAAS,YAAY,GAAG,SAAS,QAAQ;CACrD,MAAM,iBAAiB,WACrB,4BACA,cAAc,yCAAyC,YACzD;CACA,MAAM,eAAe,WACnB,kBACA,oBACA,SACF;CAEA,OACE,qBAAC,OAAD;EAAK,WAAW;EAAhB,UAAA,CACE,oBAAC,MAAD;GAAM,MAAK;GAAS,WAAU;GAAyB,eAAA;EAAa,CAAA,GACpE,oBAAC,SAAD;GACO;GACL,MAAK;GACL,WAAW;GACX,gBAAc,WAAW,KAAA;GACzB,GAAI;EACL,CAAA,CACE;;AAET,CACF;AAEA,YAAY,cAAc"}
|
package/dist/Select/Select.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { FormControlInlineSize } from "@dsn-starter-kit/core";
|
|
3
3
|
//#region src/Select/Select.d.ts
|
|
4
4
|
interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {
|
|
5
5
|
/**
|
|
@@ -8,10 +8,10 @@ interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {
|
|
|
8
8
|
*/
|
|
9
9
|
invalid?: boolean;
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
* @default undefined (uses default max-
|
|
11
|
+
* Inline-size variant for the select
|
|
12
|
+
* @default undefined (uses default max-inline-size from form-control)
|
|
13
13
|
*/
|
|
14
|
-
|
|
14
|
+
inlineSize?: FormControlInlineSize;
|
|
15
15
|
/**
|
|
16
16
|
* Additional CSS class names
|
|
17
17
|
*/
|
|
@@ -40,8 +40,8 @@ interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {
|
|
|
40
40
|
* </Select>
|
|
41
41
|
* </FormField>
|
|
42
42
|
*
|
|
43
|
-
* //
|
|
44
|
-
* <Select
|
|
43
|
+
* // Inline-size variant
|
|
44
|
+
* <Select inlineSize="lg">...</Select>
|
|
45
45
|
*
|
|
46
46
|
* // Invalid state
|
|
47
47
|
* <Select invalid aria-invalid="true" aria-describedby="error">...</Select>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.d.mts","names":[],"sources":["../../src/Select/Select.tsx"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"Select.d.mts","names":[],"sources":["../../src/Select/Select.tsx"],"mappings":";;;UAKiB,oBAAoB,MAAM,qBAAqB;;;;;EAK9D;;;;;EAMA,aAAa;;;;EAKb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAiCW,QAAM,MAAA,0BAAA,cAAA,MAAA,cAAA"}
|
package/dist/Select/Select2.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Icon } from "../Icon/Icon2.mjs";
|
|
2
|
-
/* empty css */
|
|
3
2
|
/* empty css */
|
|
4
3
|
import React from "react";
|
|
5
4
|
import { classNames } from "@dsn-starter-kit/core";
|
|
@@ -28,15 +27,15 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
28
27
|
* </Select>
|
|
29
28
|
* </FormField>
|
|
30
29
|
*
|
|
31
|
-
* //
|
|
32
|
-
* <Select
|
|
30
|
+
* // Inline-size variant
|
|
31
|
+
* <Select inlineSize="lg">...</Select>
|
|
33
32
|
*
|
|
34
33
|
* // Invalid state
|
|
35
34
|
* <Select invalid aria-invalid="true" aria-describedby="error">...</Select>
|
|
36
35
|
* ```
|
|
37
36
|
*/
|
|
38
|
-
const Select = React.forwardRef(({ className, invalid,
|
|
39
|
-
const wrapperClasses = classNames("dsn-select-wrapper",
|
|
37
|
+
const Select = React.forwardRef(({ className, invalid, inlineSize, disabled, children, ...props }, ref) => {
|
|
38
|
+
const wrapperClasses = classNames("dsn-select-wrapper", inlineSize && `dsn-select-wrapper--inline-size-${inlineSize}`);
|
|
40
39
|
const selectClasses = classNames("dsn-text-input", "dsn-select", className);
|
|
41
40
|
return /* @__PURE__ */ jsxs("div", {
|
|
42
41
|
className: wrapperClasses,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select2.mjs","names":[],"sources":["../../src/Select/Select.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames,
|
|
1
|
+
{"version":3,"file":"Select2.mjs","names":[],"sources":["../../src/Select/Select.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames, FormControlInlineSize } from '@dsn-starter-kit/core';\nimport { Icon } from '../Icon';\nimport './Select.css';\n\nexport interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {\n /**\n * Whether the select is in an invalid state\n * @default false\n */\n invalid?: boolean;\n\n /**\n * Inline-size variant for the select\n * @default undefined (uses default max-inline-size from form-control)\n */\n inlineSize?: FormControlInlineSize;\n\n /**\n * Additional CSS class names\n */\n className?: string;\n}\n\n/**\n * Select component\n * Dropdown select with a custom chevron-down icon at inline-end.\n * The native select arrow is hidden; the custom icon is decorative and non-interactive.\n *\n * @example\n * ```tsx\n * // Basic usage\n * <Select>\n * <option value=\"\">Kies een optie</option>\n * <option value=\"1\">Optie 1</option>\n * <option value=\"2\">Optie 2</option>\n * </Select>\n *\n * // With label\n * <FormField label=\"Land\" htmlFor=\"land\">\n * <Select id=\"land\">\n * <option value=\"\">Kies een land</option>\n * <option value=\"nl\">Nederland</option>\n * <option value=\"be\">België</option>\n * </Select>\n * </FormField>\n *\n * // Inline-size variant\n * <Select inlineSize=\"lg\">...</Select>\n *\n * // Invalid state\n * <Select invalid aria-invalid=\"true\" aria-describedby=\"error\">...</Select>\n * ```\n */\nexport const Select = React.forwardRef<HTMLSelectElement, SelectProps>(\n ({ className, invalid, inlineSize, disabled, children, ...props }, ref) => {\n const wrapperClasses = classNames(\n 'dsn-select-wrapper',\n inlineSize && `dsn-select-wrapper--inline-size-${inlineSize}`\n );\n\n const selectClasses = classNames('dsn-text-input', 'dsn-select', className);\n\n return (\n <div className={wrapperClasses}>\n <select\n ref={ref}\n className={selectClasses}\n aria-invalid={invalid || undefined}\n disabled={disabled}\n {...props}\n >\n {children}\n </select>\n {!disabled && (\n <Icon name=\"chevron-down\" className=\"dsn-select__icon\" aria-hidden />\n )}\n </div>\n );\n }\n);\n\nSelect.displayName = 'Select';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDA,MAAa,SAAS,MAAM,YACzB,EAAE,WAAW,SAAS,YAAY,UAAU,UAAU,GAAG,SAAS,QAAQ;CACzE,MAAM,iBAAiB,WACrB,sBACA,cAAc,mCAAmC,YACnD;CAEA,MAAM,gBAAgB,WAAW,kBAAkB,cAAc,SAAS;CAE1E,OACE,qBAAC,OAAD;EAAK,WAAW;EAAhB,UAAA,CACE,oBAAC,UAAD;GACO;GACL,WAAW;GACX,gBAAc,WAAW,KAAA;GACf;GACV,GAAI;GAEH;EACK,CAAA,GACP,CAAC,YACA,oBAAC,MAAD;GAAM,MAAK;GAAe,WAAU;GAAmB,eAAA;EAAa,CAAA,CAEnE;;AAET,CACF;AAEA,OAAO,cAAc"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { FormControlInlineSize } from "@dsn-starter-kit/core";
|
|
3
3
|
//#region src/TelephoneInput/TelephoneInput.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Inline-size variants offered by TelephoneInput. xs and sm are left out: they
|
|
6
|
+
* are too narrow for the content this field is meant for.
|
|
7
|
+
*/
|
|
8
|
+
type TelephoneInputInlineSize = Exclude<FormControlInlineSize, 'xs' | 'sm'>;
|
|
4
9
|
interface TelephoneInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'> {
|
|
5
10
|
/**
|
|
6
11
|
* Whether the input is in an invalid state
|
|
@@ -8,10 +13,10 @@ interface TelephoneInputProps extends Omit<React.InputHTMLAttributes<HTMLInputEl
|
|
|
8
13
|
*/
|
|
9
14
|
invalid?: boolean;
|
|
10
15
|
/**
|
|
11
|
-
*
|
|
12
|
-
* @default
|
|
16
|
+
* Inline-size variant for the input (md, lg, xl or full)
|
|
17
|
+
* @default 'md'
|
|
13
18
|
*/
|
|
14
|
-
|
|
19
|
+
inlineSize?: TelephoneInputInlineSize;
|
|
15
20
|
/**
|
|
16
21
|
* Additional CSS class names
|
|
17
22
|
*/
|
|
@@ -36,5 +41,5 @@ interface TelephoneInputProps extends Omit<React.InputHTMLAttributes<HTMLInputEl
|
|
|
36
41
|
*/
|
|
37
42
|
declare const TelephoneInput: React.ForwardRefExoticComponent<TelephoneInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
38
43
|
//#endregion
|
|
39
|
-
export { TelephoneInput, TelephoneInputProps };
|
|
44
|
+
export { TelephoneInput, TelephoneInputInlineSize, TelephoneInputProps };
|
|
40
45
|
//# sourceMappingURL=TelephoneInput.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TelephoneInput.d.mts","names":[],"sources":["../../src/TelephoneInput/TelephoneInput.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"TelephoneInput.d.mts","names":[],"sources":["../../src/TelephoneInput/TelephoneInput.tsx"],"mappings":";;;;;;;KAQY,2BAA2B,QACrC;UAIe,4BAA4B,KAC3C,MAAM,oBAAoB;;;;;EAO1B;;;;;EAMA,aAAa;;;;EAKb;;;;;;;;;;;;;;;;;;;cAoBW,gBAAc,MAAA,0BAAA,sBAAA,MAAA,cAAA"}
|
|
@@ -20,8 +20,8 @@ import { jsx } from "react/jsx-runtime";
|
|
|
20
20
|
* <TelephoneInput invalid aria-invalid="true" aria-describedby="error" />
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
|
-
const TelephoneInput = React.forwardRef(({ className, invalid,
|
|
24
|
-
const classes = classNames("dsn-text-input",
|
|
23
|
+
const TelephoneInput = React.forwardRef(({ className, invalid, inlineSize = "md", autoComplete, ...props }, ref) => {
|
|
24
|
+
const classes = classNames("dsn-text-input", inlineSize && `dsn-text-input--inline-size-${inlineSize}`, className);
|
|
25
25
|
return /* @__PURE__ */ jsx("input", {
|
|
26
26
|
ref,
|
|
27
27
|
type: "tel",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TelephoneInput2.mjs","names":[],"sources":["../../src/TelephoneInput/TelephoneInput.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames,
|
|
1
|
+
{"version":3,"file":"TelephoneInput2.mjs","names":[],"sources":["../../src/TelephoneInput/TelephoneInput.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames, FormControlInlineSize } from '@dsn-starter-kit/core';\nimport './TelephoneInput.css';\n\n/**\n * Inline-size variants offered by TelephoneInput. xs and sm are left out: they\n * are too narrow for the content this field is meant for.\n */\nexport type TelephoneInputInlineSize = Exclude<\n FormControlInlineSize,\n 'xs' | 'sm'\n>;\n\nexport interface TelephoneInputProps extends Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'type'\n> {\n /**\n * Whether the input is in an invalid state\n * @default false\n */\n invalid?: boolean;\n\n /**\n * Inline-size variant for the input (md, lg, xl or full)\n * @default 'md'\n */\n inlineSize?: TelephoneInputInlineSize;\n\n /**\n * Additional CSS class names\n */\n className?: string;\n}\n\n/**\n * Telephone Input component\n * Telephone input with appropriate inputmode and autocomplete\n *\n * @example\n * ```tsx\n * // Basic usage\n * <TelephoneInput placeholder=\"06 12345678\" />\n *\n * // With label\n * <FormFieldLabel htmlFor=\"phone\">Telefoonnummer</FormFieldLabel>\n * <TelephoneInput id=\"phone\" />\n *\n * // Invalid state\n * <TelephoneInput invalid aria-invalid=\"true\" aria-describedby=\"error\" />\n * ```\n */\nexport const TelephoneInput = React.forwardRef<\n HTMLInputElement,\n TelephoneInputProps\n>(({ className, invalid, inlineSize = 'md', autoComplete, ...props }, ref) => {\n const classes = classNames(\n 'dsn-text-input',\n inlineSize && `dsn-text-input--inline-size-${inlineSize}`,\n className\n );\n\n return (\n <input\n ref={ref}\n type=\"tel\"\n inputMode=\"tel\"\n className={classes}\n autoComplete={autoComplete || 'tel'}\n aria-invalid={invalid || undefined}\n {...props}\n />\n );\n});\n\nTelephoneInput.displayName = 'TelephoneInput';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAoDA,MAAa,iBAAiB,MAAM,YAGjC,EAAE,WAAW,SAAS,aAAa,MAAM,cAAc,GAAG,SAAS,QAAQ;CAC5E,MAAM,UAAU,WACd,kBACA,cAAc,+BAA+B,cAC7C,SACF;CAEA,OACE,oBAAC,SAAD;EACO;EACL,MAAK;EACL,WAAU;EACV,WAAW;EACX,cAAc,gBAAgB;EAC9B,gBAAc,WAAW,KAAA;EACzB,GAAI;CACL,CAAA;AAEL,CAAC;AAED,eAAe,cAAc"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { FormControlInlineSize } from "@dsn-starter-kit/core";
|
|
3
3
|
//#region src/TextArea/TextArea.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Inline-size variants offered by TextArea. xs and sm are left out: they
|
|
6
|
+
* are too narrow for the content this field is meant for.
|
|
7
|
+
*/
|
|
8
|
+
type TextAreaInlineSize = Exclude<FormControlInlineSize, 'xs' | 'sm'>;
|
|
4
9
|
interface TextAreaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
5
10
|
/**
|
|
6
11
|
* Additional CSS class names
|
|
@@ -12,10 +17,10 @@ interface TextAreaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement
|
|
|
12
17
|
*/
|
|
13
18
|
invalid?: boolean;
|
|
14
19
|
/**
|
|
15
|
-
*
|
|
16
|
-
* @default undefined (uses default max-
|
|
20
|
+
* Inline-size variant for the textarea (md, lg, xl or full)
|
|
21
|
+
* @default undefined (uses default max-inline-size from form-control)
|
|
17
22
|
*/
|
|
18
|
-
|
|
23
|
+
inlineSize?: TextAreaInlineSize;
|
|
19
24
|
}
|
|
20
25
|
/**
|
|
21
26
|
* Text Area component
|
|
@@ -42,5 +47,5 @@ interface TextAreaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement
|
|
|
42
47
|
*/
|
|
43
48
|
declare const TextArea: React.ForwardRefExoticComponent<TextAreaProps & React.RefAttributes<HTMLTextAreaElement>>;
|
|
44
49
|
//#endregion
|
|
45
|
-
export { TextArea, TextAreaProps };
|
|
50
|
+
export { TextArea, TextAreaInlineSize, TextAreaProps };
|
|
46
51
|
//# sourceMappingURL=TextArea.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextArea.d.mts","names":[],"sources":["../../src/TextArea/TextArea.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"TextArea.d.mts","names":[],"sources":["../../src/TextArea/TextArea.tsx"],"mappings":";;;;;;;KAQY,qBAAqB,QAAQ;UAExB,sBAAsB,MAAM,uBAAuB;;;;EAIlE;;;;;EAMA;;;;;EAMA,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;cA0BF,UAAQ,MAAA,0BAAA,gBAAA,MAAA,cAAA"}
|
|
@@ -26,8 +26,8 @@ import { jsx } from "react/jsx-runtime";
|
|
|
26
26
|
* <TextArea readOnly value="View only" rows={3} />
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
|
-
const TextArea = React.forwardRef(({ className, invalid,
|
|
30
|
-
const classes = classNames("dsn-text-area",
|
|
29
|
+
const TextArea = React.forwardRef(({ className, invalid, inlineSize, rows = 4, ...props }, ref) => {
|
|
30
|
+
const classes = classNames("dsn-text-area", inlineSize && `dsn-text-area--inline-size-${inlineSize}`, className);
|
|
31
31
|
return /* @__PURE__ */ jsx("textarea", {
|
|
32
32
|
ref,
|
|
33
33
|
className: classes,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextArea2.mjs","names":[],"sources":["../../src/TextArea/TextArea.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames,
|
|
1
|
+
{"version":3,"file":"TextArea2.mjs","names":[],"sources":["../../src/TextArea/TextArea.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames, FormControlInlineSize } from '@dsn-starter-kit/core';\nimport './TextArea.css';\n\n/**\n * Inline-size variants offered by TextArea. xs and sm are left out: they\n * are too narrow for the content this field is meant for.\n */\nexport type TextAreaInlineSize = Exclude<FormControlInlineSize, 'xs' | 'sm'>;\n\nexport interface TextAreaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {\n /**\n * Additional CSS class names\n */\n className?: string;\n\n /**\n * Whether the textarea is in an invalid state\n * @default false\n */\n invalid?: boolean;\n\n /**\n * Inline-size variant for the textarea (md, lg, xl or full)\n * @default undefined (uses default max-inline-size from form-control)\n */\n inlineSize?: TextAreaInlineSize;\n}\n\n/**\n * Text Area component\n * Multi-line text input with support for various states (hover, focus, disabled, invalid, read-only)\n *\n * @example\n * ```tsx\n * // Basic usage\n * <TextArea placeholder=\"Enter your bio\" rows={4} />\n *\n * // With label\n * <FormFieldLabel htmlFor=\"bio\">Biography</FormFieldLabel>\n * <TextArea id=\"bio\" rows={6} />\n *\n * // Disabled\n * <TextArea disabled value=\"Cannot edit\" rows={3} />\n *\n * // Invalid\n * <TextArea invalid aria-invalid=\"true\" aria-describedby=\"error\" rows={4} />\n *\n * // Read-only\n * <TextArea readOnly value=\"View only\" rows={3} />\n * ```\n */\nexport const TextArea = React.forwardRef<HTMLTextAreaElement, TextAreaProps>(\n ({ className, invalid, inlineSize, rows = 4, ...props }, ref) => {\n const classes = classNames(\n 'dsn-text-area',\n inlineSize && `dsn-text-area--inline-size-${inlineSize}`,\n className\n );\n\n return (\n <textarea\n ref={ref}\n className={classes}\n rows={rows}\n aria-invalid={invalid || undefined}\n {...props}\n />\n );\n }\n);\n\nTextArea.displayName = 'TextArea';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,MAAa,WAAW,MAAM,YAC3B,EAAE,WAAW,SAAS,YAAY,OAAO,GAAG,GAAG,SAAS,QAAQ;CAC/D,MAAM,UAAU,WACd,iBACA,cAAc,8BAA8B,cAC5C,SACF;CAEA,OACE,oBAAC,YAAD;EACO;EACL,WAAW;EACL;EACN,gBAAc,WAAW,KAAA;EACzB,GAAI;CACL,CAAA;AAEL,CACF;AAEA,SAAS,cAAc"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { FormControlInlineSize } from "@dsn-starter-kit/core";
|
|
3
3
|
//#region src/TextInput/TextInput.d.ts
|
|
4
4
|
interface TextInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
5
5
|
/**
|
|
@@ -12,10 +12,10 @@ interface TextInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
|
12
12
|
*/
|
|
13
13
|
invalid?: boolean;
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
* @default undefined (uses default max-
|
|
15
|
+
* Inline-size variant for the input
|
|
16
|
+
* @default undefined (uses default max-inline-size from form-control)
|
|
17
17
|
*/
|
|
18
|
-
|
|
18
|
+
inlineSize?: FormControlInlineSize;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* Text Input component
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextInput.d.mts","names":[],"sources":["../../src/TextInput/TextInput.tsx"],"mappings":";;;UAIiB,uBAAuB,MAAM,oBAAoB;;;;EAIhE;;;;;EAMA;;;;;EAMA,
|
|
1
|
+
{"version":3,"file":"TextInput.d.mts","names":[],"sources":["../../src/TextInput/TextInput.tsx"],"mappings":";;;UAIiB,uBAAuB,MAAM,oBAAoB;;;;EAIhE;;;;;EAMA;;;;;EAMA,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;cA0BF,WAAS,MAAA,0BAAA,iBAAA,MAAA,cAAA"}
|
|
@@ -26,8 +26,8 @@ import { jsx } from "react/jsx-runtime";
|
|
|
26
26
|
* <TextInput readOnly value="Cannot edit this" />
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
|
-
const TextInput = React.forwardRef(({ className, invalid,
|
|
30
|
-
const classes = classNames("dsn-text-input",
|
|
29
|
+
const TextInput = React.forwardRef(({ className, invalid, inlineSize, type = "text", ...props }, ref) => {
|
|
30
|
+
const classes = classNames("dsn-text-input", inlineSize && `dsn-text-input--inline-size-${inlineSize}`, className);
|
|
31
31
|
return /* @__PURE__ */ jsx("input", {
|
|
32
32
|
ref,
|
|
33
33
|
type,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextInput2.mjs","names":[],"sources":["../../src/TextInput/TextInput.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames,
|
|
1
|
+
{"version":3,"file":"TextInput2.mjs","names":[],"sources":["../../src/TextInput/TextInput.tsx"],"sourcesContent":["import React from 'react';\nimport { classNames, FormControlInlineSize } from '@dsn-starter-kit/core';\nimport './TextInput.css';\n\nexport interface TextInputProps extends React.InputHTMLAttributes<HTMLInputElement> {\n /**\n * Additional CSS class names\n */\n className?: string;\n\n /**\n * Whether the input is in an invalid state\n * @default false\n */\n invalid?: boolean;\n\n /**\n * Inline-size variant for the input\n * @default undefined (uses default max-inline-size from form-control)\n */\n inlineSize?: FormControlInlineSize;\n}\n\n/**\n * Text Input component\n * Single-line text input with support for various states (hover, focus, disabled, invalid, read-only)\n *\n * @example\n * ```tsx\n * // Basic usage\n * <TextInput placeholder=\"Enter your name\" />\n *\n * // With label\n * <FormFieldLabel htmlFor=\"email\">Email</FormFieldLabel>\n * <TextInput id=\"email\" type=\"email\" />\n *\n * // Disabled\n * <TextInput disabled value=\"Read only value\" />\n *\n * // Invalid\n * <TextInput invalid aria-invalid=\"true\" aria-describedby=\"error\" />\n *\n * // Read-only\n * <TextInput readOnly value=\"Cannot edit this\" />\n * ```\n */\nexport const TextInput = React.forwardRef<HTMLInputElement, TextInputProps>(\n ({ className, invalid, inlineSize, type = 'text', ...props }, ref) => {\n const classes = classNames(\n 'dsn-text-input',\n inlineSize && `dsn-text-input--inline-size-${inlineSize}`,\n className\n );\n\n return (\n <input\n ref={ref}\n type={type}\n className={classes}\n aria-invalid={invalid || undefined}\n {...props}\n />\n );\n }\n);\n\nTextInput.displayName = 'TextInput';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CA,MAAa,YAAY,MAAM,YAC5B,EAAE,WAAW,SAAS,YAAY,OAAO,QAAQ,GAAG,SAAS,QAAQ;CACpE,MAAM,UAAU,WACd,kBACA,cAAc,+BAA+B,cAC7C,SACF;CAEA,OACE,oBAAC,SAAD;EACO;EACC;EACN,WAAW;EACX,gBAAc,WAAW,KAAA;EACzB,GAAI;CACL,CAAA;AAEL,CACF;AAEA,UAAU,cAAc"}
|
|
@@ -14,7 +14,7 @@ interface TimeInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement
|
|
|
14
14
|
/**
|
|
15
15
|
* Time Input component
|
|
16
16
|
* Time input with an interactive clock button at inline-end that opens the native time picker.
|
|
17
|
-
* Fixed
|
|
17
|
+
* Fixed inline-size (sm): not configurable, as time inputs have a predictable content length.
|
|
18
18
|
*
|
|
19
19
|
* @example
|
|
20
20
|
* ```tsx
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeInput.d.mts","names":[],"sources":["../../src/TimeInput/TimeInput.tsx"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"TimeInput.d.mts","names":[],"sources":["../../src/TimeInput/TimeInput.tsx"],"mappings":";;UAMiB,uBAAuB,KACtC,MAAM,oBAAoB;;;;;EAO1B;;;;EAKA;;;;;;;;;;;;;;;;;;;;;;;cAwBW,WAAS,MAAA,0BAAA,iBAAA,MAAA,cAAA"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Icon } from "../Icon/Icon2.mjs";
|
|
2
2
|
import { Button } from "../Button/Button2.mjs";
|
|
3
|
-
/* empty css */
|
|
4
3
|
/* empty css */
|
|
5
4
|
import React from "react";
|
|
6
5
|
import { classNames } from "@dsn-starter-kit/core";
|
|
@@ -9,7 +8,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
9
8
|
/**
|
|
10
9
|
* Time Input component
|
|
11
10
|
* Time input with an interactive clock button at inline-end that opens the native time picker.
|
|
12
|
-
* Fixed
|
|
11
|
+
* Fixed inline-size (sm): not configurable, as time inputs have a predictable content length.
|
|
13
12
|
*
|
|
14
13
|
* @example
|
|
15
14
|
* ```tsx
|