@1e99/components 0.2.1 → 0.2.2

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/index.d.ts CHANGED
@@ -36,7 +36,9 @@ type SelectorRenderTriggerContext<TOption extends SelectorOption> = {
36
36
  };
37
37
  type SelectorBaseProps = {
38
38
  label: string;
39
+ showTriggerIndicator?: boolean;
39
40
  triggerAriaLabel?: string;
41
+ triggerClassName?: string;
40
42
  value: string;
41
43
  };
42
44
  type SelectorProps<TOption extends SelectorOption = SelectorOption> = SelectorBaseProps & {
@@ -47,7 +49,7 @@ type SelectorProps<TOption extends SelectorOption = SelectorOption> = SelectorBa
47
49
  renderTrigger?: (context: SelectorRenderTriggerContext<TOption>) => ReactNode;
48
50
  whiteSurface?: boolean;
49
51
  };
50
- declare function Selector<TOption extends SelectorOption = SelectorOption>({ density, label, onValueChange, options, renderOption, renderTrigger, triggerAriaLabel, value, whiteSurface, }: SelectorProps<TOption>): react.JSX.Element;
52
+ declare function Selector<TOption extends SelectorOption = SelectorOption>({ density, label, onValueChange, options, renderOption, renderTrigger, showTriggerIndicator, triggerAriaLabel, triggerClassName, value, whiteSurface, }: SelectorProps<TOption>): react.JSX.Element;
51
53
 
52
54
  type NavbarItem = {
53
55
  href: string;
package/dist/index.js CHANGED
@@ -51,7 +51,9 @@ function SelectorTrigger({
51
51
  optionListId,
52
52
  renderTrigger,
53
53
  selectedOption,
54
+ showTriggerIndicator,
54
55
  triggerAriaLabel,
56
+ triggerClassName,
55
57
  value
56
58
  }) {
57
59
  const triggerContent = renderTrigger?.({ selectedOption, value }) ?? selectedOption?.label ?? value;
@@ -61,18 +63,18 @@ function SelectorTrigger({
61
63
  "aria-controls": optionListId,
62
64
  "aria-expanded": isOpen,
63
65
  "aria-label": triggerAriaLabel,
64
- className: `${standardTriggerClassName} ${densityClassName}`,
66
+ className: triggerClassName ?? `${standardTriggerClassName} ${densityClassName}`,
65
67
  onClick,
66
68
  type: "button",
67
69
  children: [
68
70
  /* @__PURE__ */ jsx2("span", { children: triggerContent }),
69
- /* @__PURE__ */ jsx2(
71
+ showTriggerIndicator ? /* @__PURE__ */ jsx2(
70
72
  LuChevronDown,
71
73
  {
72
74
  "aria-hidden": "true",
73
75
  className: `selector-disclosure-arrow size-5 shrink-0 text-content-secondary transition-transform duration-200 ease-brand motion-reduce:transition-none ${isOpen ? "rotate-180" : ""}`
74
76
  }
75
- )
77
+ ) : null
76
78
  ]
77
79
  }
78
80
  );
@@ -84,7 +86,9 @@ function Selector({
84
86
  options,
85
87
  renderOption,
86
88
  renderTrigger,
89
+ showTriggerIndicator = true,
87
90
  triggerAriaLabel,
91
+ triggerClassName,
88
92
  value,
89
93
  whiteSurface = false
90
94
  }) {
@@ -137,7 +141,9 @@ function Selector({
137
141
  optionListId,
138
142
  renderTrigger,
139
143
  selectedOption,
144
+ showTriggerIndicator,
140
145
  triggerAriaLabel,
146
+ triggerClassName,
141
147
  value
142
148
  }
143
149
  ),
@@ -201,7 +207,7 @@ function AccountControl({
201
207
  /* @__PURE__ */ jsx3(
202
208
  "span",
203
209
  {
204
- className: "w-full truncate text-ui font-semibold text-content-primary",
210
+ className: "w-full break-words text-ui font-semibold text-content-primary",
205
211
  title: identity,
206
212
  children: identity
207
213
  }
@@ -209,7 +215,7 @@ function AccountControl({
209
215
  showEmail ? /* @__PURE__ */ jsx3(
210
216
  "span",
211
217
  {
212
- className: "mt-1 w-full truncate text-label text-content-secondary",
218
+ className: "mt-1 w-full break-all text-label text-content-secondary",
213
219
  title: email ?? void 0,
214
220
  children: email
215
221
  }
@@ -219,18 +225,10 @@ function AccountControl({
219
225
  /* @__PURE__ */ jsx3("span", { "aria-hidden": "true", children: option.label }),
220
226
  /* @__PURE__ */ jsx3("span", { className: "sr-only", children: signOutAriaLabel })
221
227
  ] }),
222
- renderTrigger: () => /* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 items-center gap-3", children: [
223
- /* @__PURE__ */ jsx3(
224
- "span",
225
- {
226
- "aria-hidden": "true",
227
- className: "flex size-8 shrink-0 items-center justify-center rounded-full bg-brand-yellow font-data text-label font-semibold text-brand-navy-dark",
228
- children: initials
229
- }
230
- ),
231
- /* @__PURE__ */ jsx3("span", { className: "text-label font-semibold md:hidden", children: menuText })
232
- ] }),
228
+ renderTrigger: () => /* @__PURE__ */ jsx3("span", { "aria-hidden": "true", children: initials }),
229
+ showTriggerIndicator: false,
233
230
  triggerAriaLabel: `${initials} ${menuAriaLabel}`,
231
+ triggerClassName: "flex size-10 cursor-pointer select-none items-center justify-center rounded-full bg-brand-yellow font-data text-label font-semibold text-brand-navy-dark transition-colors duration-200 ease-brand hover:bg-brand-yellow/85 focus-visible:outline-none focus-visible:shadow-focus",
234
232
  value: "account"
235
233
  }
236
234
  );
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/google-sign-in-button/google-sign-in-button.tsx","../src/components/account-control/account-control.tsx","../src/utils/get-initials.ts","../src/components/selector/selector.tsx","../src/components/navbar/navbar.tsx"],"sourcesContent":["import type {ButtonHTMLAttributes, ReactNode} from 'react';\nimport {FcGoogle} from 'react-icons/fc';\n\nexport type GoogleSignInButtonProps = Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n 'children' | 'className' | 'type'\n> & {\n label: ReactNode;\n};\n\nconst buttonClassName =\n 'inline-flex min-h-12 w-full cursor-pointer items-center justify-center gap-3 rounded-control border border-border-subtle bg-surface-raised px-control-x py-control-y text-label font-semibold whitespace-nowrap text-content-primary shadow-card transition-[translate,scale,background-color] duration-200 ease-brand hover:-translate-y-0.5 hover:bg-brand-cloud active:scale-[0.97] focus-visible:outline-none focus-visible:shadow-focus disabled:cursor-wait disabled:opacity-70 motion-reduce:transform-none';\n\nexport function GoogleSignInButton(\n {label, ...buttonProps}: GoogleSignInButtonProps,\n) {\n return (\n <button {...buttonProps} className={buttonClassName} type=\"button\">\n <FcGoogle\n aria-hidden=\"true\"\n className=\"size-5 shrink-0\"\n data-testid=\"google-mark\"\n />\n {label}\n </button>\n );\n}\n","import {LuLogOut} from 'react-icons/lu';\nimport {getInitials} from '../../utils/get-initials';\nimport {Selector} from '../selector/selector';\n\nexport type AccountControlProps = {\n email?: string | null;\n fallbackIdentity: string;\n menuAriaLabel: string;\n menuText: string;\n name?: string | null;\n onSignOut: () => void;\n signOutAriaLabel: string;\n signOutText: string;\n};\n\nexport function AccountControl({\n email,\n fallbackIdentity,\n menuAriaLabel,\n menuText,\n name,\n onSignOut,\n signOutAriaLabel,\n signOutText,\n}: AccountControlProps) {\n const normalizedName = name?.trim();\n const identity = normalizedName || email || fallbackIdentity;\n const initials = getInitials(identity);\n const showEmail = Boolean(email && email !== identity);\n const options = [\n {label: identity, value: 'account'},\n {label: signOutText, value: 'sign-out'},\n ];\n\n return (\n <Selector\n label={menuText}\n onValueChange={(value) => {\n if (value === 'sign-out') {\n onSignOut();\n }\n }}\n options={options}\n renderOption={({option}) => option.value === 'account' ? (\n <span data-account-identity className=\"flex min-w-0 flex-col items-start py-1\">\n <span\n className=\"w-full truncate text-ui font-semibold text-content-primary\"\n title={identity}\n >\n {identity}\n </span>\n {showEmail ? (\n <span\n className=\"mt-1 w-full truncate text-label text-content-secondary\"\n title={email ?? undefined}\n >\n {email}\n </span>\n ) : null}\n </span>\n ) : (\n <span className=\"flex items-center gap-3\">\n <LuLogOut aria-hidden=\"true\" className=\"size-5 shrink-0\" />\n <span aria-hidden=\"true\">{option.label}</span>\n <span className=\"sr-only\">{signOutAriaLabel}</span>\n </span>\n )}\n renderTrigger={() => (\n <span className=\"flex min-w-0 items-center gap-3\">\n <span\n aria-hidden=\"true\"\n className=\"flex size-8 shrink-0 items-center justify-center rounded-full bg-brand-yellow font-data text-label font-semibold text-brand-navy-dark\"\n >\n {initials}\n </span>\n <span className=\"text-label font-semibold md:hidden\">{menuText}</span>\n </span>\n )}\n triggerAriaLabel={`${initials} ${menuAriaLabel}`}\n value=\"account\"\n />\n );\n}\n","export function getInitials(value: string) {\n const parts = value.trim().split(/\\s+/).filter(Boolean);\n const selected = parts.length > 1 ? [parts[0], parts.at(-1)!] : parts;\n\n return (\n selected\n .map((part) => Array.from(part)[0])\n .join('')\n .toUpperCase()\n .slice(0, 2) || '1'\n );\n}\n","import {type ReactNode, useEffect, useId, useRef, useState} from 'react';\nimport {LuChevronDown} from 'react-icons/lu';\n\nexport type SelectorOption = {\n label: ReactNode;\n value: string;\n};\n\nexport type SelectorDensity = 'compact' | 'compact-mobile' | 'standard';\n\nexport type SelectorRenderOptionContext<TOption extends SelectorOption> = {\n isSelected: boolean;\n option: TOption;\n select: () => void;\n};\n\nexport type SelectorRenderTriggerContext<TOption extends SelectorOption> = {\n selectedOption: TOption | undefined;\n value: string;\n};\n\ntype SelectorBaseProps = {\n label: string;\n triggerAriaLabel?: string;\n value: string;\n};\n\nexport type SelectorProps<TOption extends SelectorOption = SelectorOption> =\n SelectorBaseProps & {\n density?: SelectorDensity;\n onValueChange: (value: string) => void;\n options: readonly TOption[];\n renderOption?: (context: SelectorRenderOptionContext<TOption>) => ReactNode;\n renderTrigger?: (\n context: SelectorRenderTriggerContext<TOption>,\n ) => ReactNode;\n whiteSurface?: boolean;\n };\n\nconst standardTriggerClassName =\n 'flex w-full cursor-pointer select-none items-center justify-between rounded-control border border-border-subtle py-control-y text-label font-semibold text-content-primary shadow-card transition-colors duration-200 ease-brand hover:bg-brand-cloud focus-visible:outline-none focus-visible:shadow-focus';\n\nconst optionClassName =\n 'flex min-h-12 w-full select-none items-center rounded-control px-3 text-label font-semibold text-content-secondary transition-colors duration-200 ease-brand hover:bg-brand-cloud hover:text-content-primary focus-visible:outline-none focus-visible:shadow-focus';\n\nfunction getNavigationLayout(density: SelectorDensity) {\n if (density === 'compact') {\n return {trigger: 'h-12 gap-2', wrapper: 'w-auto'};\n }\n\n if (density === 'compact-mobile') {\n return {\n trigger: 'h-12 gap-2 px-3 md:gap-4 md:px-4 md:min-w-32',\n wrapper: 'w-auto',\n };\n }\n\n return {trigger: 'min-h-12 gap-4 px-4 md:min-w-32', wrapper: 'w-full md:w-auto'};\n}\n\nfunction SelectorTrigger<TOption extends SelectorOption>({\n densityClassName,\n isOpen,\n onClick,\n optionListId,\n renderTrigger,\n selectedOption,\n triggerAriaLabel,\n value,\n}: {\n densityClassName: string;\n isOpen: boolean;\n onClick: () => void;\n optionListId: string;\n renderTrigger?: (context: SelectorRenderTriggerContext<TOption>) => ReactNode;\n selectedOption: TOption | undefined;\n triggerAriaLabel?: string;\n value: string;\n}) {\n const triggerContent = renderTrigger?.({selectedOption, value}) ??\n selectedOption?.label ?? value;\n\n return (\n <button\n aria-controls={optionListId}\n aria-expanded={isOpen}\n aria-label={triggerAriaLabel}\n className={`${standardTriggerClassName} ${densityClassName}`}\n onClick={onClick}\n type=\"button\"\n >\n <span>{triggerContent}</span>\n <LuChevronDown\n aria-hidden=\"true\"\n className={`selector-disclosure-arrow size-5 shrink-0 text-content-secondary transition-transform duration-200 ease-brand motion-reduce:transition-none ${isOpen ? 'rotate-180' : ''}`}\n />\n </button>\n );\n}\n\nexport function Selector<TOption extends SelectorOption = SelectorOption>({\n density = 'standard',\n label,\n onValueChange,\n options,\n renderOption,\n renderTrigger,\n triggerAriaLabel,\n value,\n whiteSurface = false,\n}: SelectorProps<TOption>) {\n const [isOpen, setIsOpen] = useState(false);\n const [selectionRequest, setSelectionRequest] =\n useState<{value: string} | null>(null);\n const optionListId = useId();\n const notifiedSelectionReference = useRef<{value: string} | null>(null);\n const onValueChangeReference = useRef(onValueChange);\n const selectorReference = useRef<HTMLDivElement>(null);\n const selectedOption = options.find((option) => option.value === value);\n const layout = getNavigationLayout(density);\n const surfaceClassName = whiteSurface ? 'bg-white' : 'bg-surface-raised';\n\n useEffect(() => {\n if (!isOpen) {\n return;\n }\n\n const closeWhenPointerStartsOutside = (event: PointerEvent) => {\n const selectorElement = selectorReference.current;\n\n if (\n !selectorElement ||\n !(event.target instanceof Node) ||\n selectorElement.contains(event.target)\n ) {\n return;\n }\n\n setIsOpen(false);\n };\n\n document.addEventListener('pointerdown', closeWhenPointerStartsOutside, true);\n\n return () => {\n document.removeEventListener('pointerdown', closeWhenPointerStartsOutside, true);\n };\n }, [isOpen]);\n\n useEffect(() => {\n onValueChangeReference.current = onValueChange;\n }, [onValueChange]);\n\n useEffect(() => {\n if (\n isOpen ||\n selectionRequest === null ||\n selectionRequest === notifiedSelectionReference.current\n ) {\n return;\n }\n\n notifiedSelectionReference.current = selectionRequest;\n onValueChangeReference.current(selectionRequest.value);\n }, [isOpen, selectionRequest]);\n\n const selectOption = (nextValue: string) => {\n setIsOpen(false);\n setSelectionRequest({value: nextValue});\n };\n\n return (\n <div ref={selectorReference} className={`selector-disclosure relative ${layout.wrapper}`}>\n <SelectorTrigger\n densityClassName={layout.trigger}\n isOpen={isOpen}\n onClick={() => setIsOpen((currentOpen) => !currentOpen)}\n optionListId={optionListId}\n renderTrigger={renderTrigger}\n selectedOption={selectedOption}\n triggerAriaLabel={triggerAriaLabel}\n value={value}\n />\n {isOpen ? (\n <ul\n aria-label={label}\n className={`mt-2 w-full overflow-hidden rounded-control border border-border-subtle ${surfaceClassName} p-1 shadow-float md:absolute md:top-full md:right-0 md:z-60 md:min-w-44`}\n id={optionListId}\n >\n {options.map((option) => {\n const isSelected = option.value === value;\n const select = () => selectOption(option.value);\n const optionContent =\n renderOption?.({isSelected, option, select}) ?? option.label;\n\n return (\n <li key={option.value}>\n <button\n aria-pressed={isSelected}\n className={`${optionClassName} text-left ${isSelected ? 'bg-brand-cloud text-content-primary' : ''}`}\n onClick={select}\n type=\"button\"\n >\n {optionContent}\n </button>\n </li>\n );\n })}\n </ul>\n ) : null}\n </div>\n );\n}\n","import {Fragment, type ReactNode, useId} from 'react';\nimport {LuMenu} from 'react-icons/lu';\n\nexport type NavbarItem = {\n href: string;\n label: ReactNode;\n};\n\nexport type NavbarLinkRenderer = (props: {\n children: ReactNode;\n className: string;\n href: string;\n}) => ReactNode;\n\nexport type NavbarWidth = 'content' | 'wide';\nexport type NavbarLinkTreatment = 'plain' | 'underlined';\nexport type NavbarLinkWeight = 'bold' | 'semibold';\nexport type NavbarLayer = 'above' | 'standard';\nexport type NavbarMobileNavigation = {\n actions?: ReactNode;\n menuLabel: string;\n navigationLabel: string;\n};\n\nexport type NavbarProps = {\n actions?: ReactNode;\n brand: ReactNode;\n items: readonly NavbarItem[];\n layer?: NavbarLayer;\n linkTreatment?: NavbarLinkTreatment;\n linkWeight?: NavbarLinkWeight;\n mobileNavigation?: NavbarMobileNavigation;\n navigationLabel: string;\n renderLink?: NavbarLinkRenderer;\n width?: NavbarWidth;\n};\n\nconst baseLinkClassName =\n 'text-label text-content-secondary transition-colors duration-200 ease-brand hover:text-content-primary focus-visible:rounded-control focus-visible:outline-none focus-visible:shadow-focus';\n\nconst underlinedLinkClassName =\n 'relative after:absolute after:-bottom-1.5 after:left-0 after:h-0.5 after:w-full after:origin-left after:scale-x-0 after:bg-action-primary after:transition-transform after:duration-200 after:ease-brand hover:after:scale-x-100 focus-visible:after:scale-x-100';\n\nconst mobileLinkClassName =\n 'flex min-h-12 items-center rounded-control px-3 text-label font-semibold text-content-secondary transition-colors duration-200 ease-brand hover:text-content-primary focus-visible:outline-none focus-visible:shadow-focus';\n\nexport function Navbar({\n actions,\n brand,\n items,\n layer = 'standard',\n linkTreatment = 'plain',\n linkWeight = 'semibold',\n mobileNavigation,\n navigationLabel,\n renderLink,\n width = 'content',\n}: NavbarProps) {\n const mobileNavigationReference = useId();\n const mobileNavigationId = `navbar-mobile-navigation-${mobileNavigationReference}`;\n const mobileNavigationAnchorName = `--navbar-mobile-menu-trigger-${mobileNavigationReference.replace(/[^a-zA-Z0-9_-]/g, '-')}`;\n const linkClassName = [\n baseLinkClassName,\n linkWeight === 'bold' ? 'font-bold' : 'font-semibold',\n linkTreatment === 'underlined' ? underlinedLinkClassName : '',\n ]\n .filter(Boolean)\n .join(' ');\n const containerWidthClassName = width === 'wide' ? 'max-w-7xl' : 'max-w-5xl';\n const layerClassName = layer === 'above' ? 'z-50' : 'z-40';\n const renderLinks = (className: string) =>\n items.map((item) => (\n <Fragment key={item.href}>\n {renderLink ? (\n renderLink({\n children: item.label,\n className,\n href: item.href,\n })\n ) : (\n <a className={className} href={item.href}>\n {item.label}\n </a>\n )}\n </Fragment>\n ));\n\n return (\n <header\n className={`sticky top-0 ${layerClassName} border-b border-border-subtle bg-surface-page/90 text-label font-semibold backdrop-blur-lg`}\n >\n <div\n className={`mx-auto flex min-h-20 ${containerWidthClassName} items-center justify-between gap-4 px-shell`}\n >\n <div className=\"shrink-0\">{brand}</div>\n <nav aria-label={navigationLabel} className=\"hidden items-center gap-6 lg:flex\">\n {renderLinks(linkClassName)}\n </nav>\n {actions}\n {mobileNavigation ? (\n <div className=\"relative md:hidden\">\n <button\n aria-controls={mobileNavigationId}\n aria-label={mobileNavigation.menuLabel}\n className=\"flex size-12 cursor-pointer items-center justify-center rounded-control bg-action-primary text-content-inverse shadow-card transition-[translate,scale,background-color] duration-200 ease-brand active:scale-[0.97] focus-visible:outline-none focus-visible:shadow-focus\"\n popoverTarget={mobileNavigationId}\n popoverTargetAction=\"toggle\"\n style={{anchorName: mobileNavigationAnchorName}}\n type=\"button\"\n >\n <span className=\"sr-only\">{mobileNavigation.menuLabel}</span>\n <LuMenu aria-hidden=\"true\" className=\"size-6\" />\n </button>\n <nav\n aria-label={mobileNavigation.navigationLabel}\n className=\"fixed top-[4.5rem] right-[1.25rem] m-0 w-72 rounded-card border border-border-subtle bg-surface-raised p-3 shadow-float [@supports(position-anchor:--navbar-mobile-menu-trigger)]:absolute [@supports(position-anchor:--navbar-mobile-menu-trigger)]:top-[calc(anchor(bottom)+0.5rem)] [@supports(position-anchor:--navbar-mobile-menu-trigger)]:right-auto [@supports(position-anchor:--navbar-mobile-menu-trigger)]:left-[anchor(right)] [@supports(position-anchor:--navbar-mobile-menu-trigger)]:-translate-x-full\"\n id={mobileNavigationId}\n popover=\"auto\"\n style={{positionAnchor: mobileNavigationAnchorName}}\n >\n {renderLinks(mobileLinkClassName)}\n {mobileNavigation.actions ? (\n <div className=\"mt-2 space-y-3 border-t border-border-subtle pt-3\">\n {mobileNavigation.actions}\n </div>\n ) : null}\n </nav>\n </div>\n ) : null}\n </div>\n </header>\n );\n}\n"],"mappings":"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","names":["jsx","jsxs","jsx","jsxs","useId","jsx","jsxs"]}
1
+ {"version":3,"sources":["../src/components/google-sign-in-button/google-sign-in-button.tsx","../src/components/account-control/account-control.tsx","../src/utils/get-initials.ts","../src/components/selector/selector.tsx","../src/components/navbar/navbar.tsx"],"sourcesContent":["import type {ButtonHTMLAttributes, ReactNode} from 'react';\nimport {FcGoogle} from 'react-icons/fc';\n\nexport type GoogleSignInButtonProps = Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n 'children' | 'className' | 'type'\n> & {\n label: ReactNode;\n};\n\nconst buttonClassName =\n 'inline-flex min-h-12 w-full cursor-pointer items-center justify-center gap-3 rounded-control border border-border-subtle bg-surface-raised px-control-x py-control-y text-label font-semibold whitespace-nowrap text-content-primary shadow-card transition-[translate,scale,background-color] duration-200 ease-brand hover:-translate-y-0.5 hover:bg-brand-cloud active:scale-[0.97] focus-visible:outline-none focus-visible:shadow-focus disabled:cursor-wait disabled:opacity-70 motion-reduce:transform-none';\n\nexport function GoogleSignInButton(\n {label, ...buttonProps}: GoogleSignInButtonProps,\n) {\n return (\n <button {...buttonProps} className={buttonClassName} type=\"button\">\n <FcGoogle\n aria-hidden=\"true\"\n className=\"size-5 shrink-0\"\n data-testid=\"google-mark\"\n />\n {label}\n </button>\n );\n}\n","import {LuLogOut} from 'react-icons/lu';\nimport {getInitials} from '../../utils/get-initials';\nimport {Selector} from '../selector/selector';\n\nexport type AccountControlProps = {\n email?: string | null;\n fallbackIdentity: string;\n menuAriaLabel: string;\n menuText: string;\n name?: string | null;\n onSignOut: () => void;\n signOutAriaLabel: string;\n signOutText: string;\n};\n\nexport function AccountControl({\n email,\n fallbackIdentity,\n menuAriaLabel,\n menuText,\n name,\n onSignOut,\n signOutAriaLabel,\n signOutText,\n}: AccountControlProps) {\n const normalizedName = name?.trim();\n const identity = normalizedName || email || fallbackIdentity;\n const initials = getInitials(identity);\n const showEmail = Boolean(email && email !== identity);\n const options = [\n {label: identity, value: 'account'},\n {label: signOutText, value: 'sign-out'},\n ];\n\n return (\n <Selector\n label={menuText}\n onValueChange={(value) => {\n if (value === 'sign-out') {\n onSignOut();\n }\n }}\n options={options}\n renderOption={({option}) => option.value === 'account' ? (\n <span data-account-identity className=\"flex min-w-0 flex-col items-start py-1\">\n <span\n className=\"w-full break-words text-ui font-semibold text-content-primary\"\n title={identity}\n >\n {identity}\n </span>\n {showEmail ? (\n <span\n className=\"mt-1 w-full break-all text-label text-content-secondary\"\n title={email ?? undefined}\n >\n {email}\n </span>\n ) : null}\n </span>\n ) : (\n <span className=\"flex items-center gap-3\">\n <LuLogOut aria-hidden=\"true\" className=\"size-5 shrink-0\" />\n <span aria-hidden=\"true\">{option.label}</span>\n <span className=\"sr-only\">{signOutAriaLabel}</span>\n </span>\n )}\n renderTrigger={() => (\n <span aria-hidden=\"true\">{initials}</span>\n )}\n showTriggerIndicator={false}\n triggerAriaLabel={`${initials} ${menuAriaLabel}`}\n triggerClassName=\"flex size-10 cursor-pointer select-none items-center justify-center rounded-full bg-brand-yellow font-data text-label font-semibold text-brand-navy-dark transition-colors duration-200 ease-brand hover:bg-brand-yellow/85 focus-visible:outline-none focus-visible:shadow-focus\"\n value=\"account\"\n />\n );\n}\n","export function getInitials(value: string) {\n const parts = value.trim().split(/\\s+/).filter(Boolean);\n const selected = parts.length > 1 ? [parts[0], parts.at(-1)!] : parts;\n\n return (\n selected\n .map((part) => Array.from(part)[0])\n .join('')\n .toUpperCase()\n .slice(0, 2) || '1'\n );\n}\n","import {type ReactNode, useEffect, useId, useRef, useState} from 'react';\nimport {LuChevronDown} from 'react-icons/lu';\n\nexport type SelectorOption = {\n label: ReactNode;\n value: string;\n};\n\nexport type SelectorDensity = 'compact' | 'compact-mobile' | 'standard';\n\nexport type SelectorRenderOptionContext<TOption extends SelectorOption> = {\n isSelected: boolean;\n option: TOption;\n select: () => void;\n};\n\nexport type SelectorRenderTriggerContext<TOption extends SelectorOption> = {\n selectedOption: TOption | undefined;\n value: string;\n};\n\ntype SelectorBaseProps = {\n label: string;\n showTriggerIndicator?: boolean;\n triggerAriaLabel?: string;\n triggerClassName?: string;\n value: string;\n};\n\nexport type SelectorProps<TOption extends SelectorOption = SelectorOption> =\n SelectorBaseProps & {\n density?: SelectorDensity;\n onValueChange: (value: string) => void;\n options: readonly TOption[];\n renderOption?: (context: SelectorRenderOptionContext<TOption>) => ReactNode;\n renderTrigger?: (\n context: SelectorRenderTriggerContext<TOption>,\n ) => ReactNode;\n whiteSurface?: boolean;\n };\n\nconst standardTriggerClassName =\n 'flex w-full cursor-pointer select-none items-center justify-between rounded-control border border-border-subtle py-control-y text-label font-semibold text-content-primary shadow-card transition-colors duration-200 ease-brand hover:bg-brand-cloud focus-visible:outline-none focus-visible:shadow-focus';\n\nconst optionClassName =\n 'flex min-h-12 w-full select-none items-center rounded-control px-3 text-label font-semibold text-content-secondary transition-colors duration-200 ease-brand hover:bg-brand-cloud hover:text-content-primary focus-visible:outline-none focus-visible:shadow-focus';\n\nfunction getNavigationLayout(density: SelectorDensity) {\n if (density === 'compact') {\n return {trigger: 'h-12 gap-2', wrapper: 'w-auto'};\n }\n\n if (density === 'compact-mobile') {\n return {\n trigger: 'h-12 gap-2 px-3 md:gap-4 md:px-4 md:min-w-32',\n wrapper: 'w-auto',\n };\n }\n\n return {trigger: 'min-h-12 gap-4 px-4 md:min-w-32', wrapper: 'w-full md:w-auto'};\n}\n\nfunction SelectorTrigger<TOption extends SelectorOption>({\n densityClassName,\n isOpen,\n onClick,\n optionListId,\n renderTrigger,\n selectedOption,\n showTriggerIndicator,\n triggerAriaLabel,\n triggerClassName,\n value,\n}: {\n densityClassName: string;\n isOpen: boolean;\n onClick: () => void;\n optionListId: string;\n renderTrigger?: (context: SelectorRenderTriggerContext<TOption>) => ReactNode;\n selectedOption: TOption | undefined;\n showTriggerIndicator: boolean;\n triggerAriaLabel?: string;\n triggerClassName?: string;\n value: string;\n}) {\n const triggerContent = renderTrigger?.({selectedOption, value}) ??\n selectedOption?.label ?? value;\n\n return (\n <button\n aria-controls={optionListId}\n aria-expanded={isOpen}\n aria-label={triggerAriaLabel}\n className={triggerClassName ?? `${standardTriggerClassName} ${densityClassName}`}\n onClick={onClick}\n type=\"button\"\n >\n <span>{triggerContent}</span>\n {showTriggerIndicator ? (\n <LuChevronDown\n aria-hidden=\"true\"\n className={`selector-disclosure-arrow size-5 shrink-0 text-content-secondary transition-transform duration-200 ease-brand motion-reduce:transition-none ${isOpen ? 'rotate-180' : ''}`}\n />\n ) : null}\n </button>\n );\n}\n\nexport function Selector<TOption extends SelectorOption = SelectorOption>({\n density = 'standard',\n label,\n onValueChange,\n options,\n renderOption,\n renderTrigger,\n showTriggerIndicator = true,\n triggerAriaLabel,\n triggerClassName,\n value,\n whiteSurface = false,\n}: SelectorProps<TOption>) {\n const [isOpen, setIsOpen] = useState(false);\n const [selectionRequest, setSelectionRequest] =\n useState<{value: string} | null>(null);\n const optionListId = useId();\n const notifiedSelectionReference = useRef<{value: string} | null>(null);\n const onValueChangeReference = useRef(onValueChange);\n const selectorReference = useRef<HTMLDivElement>(null);\n const selectedOption = options.find((option) => option.value === value);\n const layout = getNavigationLayout(density);\n const surfaceClassName = whiteSurface ? 'bg-white' : 'bg-surface-raised';\n\n useEffect(() => {\n if (!isOpen) {\n return;\n }\n\n const closeWhenPointerStartsOutside = (event: PointerEvent) => {\n const selectorElement = selectorReference.current;\n\n if (\n !selectorElement ||\n !(event.target instanceof Node) ||\n selectorElement.contains(event.target)\n ) {\n return;\n }\n\n setIsOpen(false);\n };\n\n document.addEventListener('pointerdown', closeWhenPointerStartsOutside, true);\n\n return () => {\n document.removeEventListener('pointerdown', closeWhenPointerStartsOutside, true);\n };\n }, [isOpen]);\n\n useEffect(() => {\n onValueChangeReference.current = onValueChange;\n }, [onValueChange]);\n\n useEffect(() => {\n if (\n isOpen ||\n selectionRequest === null ||\n selectionRequest === notifiedSelectionReference.current\n ) {\n return;\n }\n\n notifiedSelectionReference.current = selectionRequest;\n onValueChangeReference.current(selectionRequest.value);\n }, [isOpen, selectionRequest]);\n\n const selectOption = (nextValue: string) => {\n setIsOpen(false);\n setSelectionRequest({value: nextValue});\n };\n\n return (\n <div ref={selectorReference} className={`selector-disclosure relative ${layout.wrapper}`}>\n <SelectorTrigger\n densityClassName={layout.trigger}\n isOpen={isOpen}\n onClick={() => setIsOpen((currentOpen) => !currentOpen)}\n optionListId={optionListId}\n renderTrigger={renderTrigger}\n selectedOption={selectedOption}\n showTriggerIndicator={showTriggerIndicator}\n triggerAriaLabel={triggerAriaLabel}\n triggerClassName={triggerClassName}\n value={value}\n />\n {isOpen ? (\n <ul\n aria-label={label}\n className={`mt-2 w-full overflow-hidden rounded-control border border-border-subtle ${surfaceClassName} p-1 shadow-float md:absolute md:top-full md:right-0 md:z-60 md:min-w-44`}\n id={optionListId}\n >\n {options.map((option) => {\n const isSelected = option.value === value;\n const select = () => selectOption(option.value);\n const optionContent =\n renderOption?.({isSelected, option, select}) ?? option.label;\n\n return (\n <li key={option.value}>\n <button\n aria-pressed={isSelected}\n className={`${optionClassName} text-left ${isSelected ? 'bg-brand-cloud text-content-primary' : ''}`}\n onClick={select}\n type=\"button\"\n >\n {optionContent}\n </button>\n </li>\n );\n })}\n </ul>\n ) : null}\n </div>\n );\n}\n","import {Fragment, type ReactNode, useId} from 'react';\nimport {LuMenu} from 'react-icons/lu';\n\nexport type NavbarItem = {\n href: string;\n label: ReactNode;\n};\n\nexport type NavbarLinkRenderer = (props: {\n children: ReactNode;\n className: string;\n href: string;\n}) => ReactNode;\n\nexport type NavbarWidth = 'content' | 'wide';\nexport type NavbarLinkTreatment = 'plain' | 'underlined';\nexport type NavbarLinkWeight = 'bold' | 'semibold';\nexport type NavbarLayer = 'above' | 'standard';\nexport type NavbarMobileNavigation = {\n actions?: ReactNode;\n menuLabel: string;\n navigationLabel: string;\n};\n\nexport type NavbarProps = {\n actions?: ReactNode;\n brand: ReactNode;\n items: readonly NavbarItem[];\n layer?: NavbarLayer;\n linkTreatment?: NavbarLinkTreatment;\n linkWeight?: NavbarLinkWeight;\n mobileNavigation?: NavbarMobileNavigation;\n navigationLabel: string;\n renderLink?: NavbarLinkRenderer;\n width?: NavbarWidth;\n};\n\nconst baseLinkClassName =\n 'text-label text-content-secondary transition-colors duration-200 ease-brand hover:text-content-primary focus-visible:rounded-control focus-visible:outline-none focus-visible:shadow-focus';\n\nconst underlinedLinkClassName =\n 'relative after:absolute after:-bottom-1.5 after:left-0 after:h-0.5 after:w-full after:origin-left after:scale-x-0 after:bg-action-primary after:transition-transform after:duration-200 after:ease-brand hover:after:scale-x-100 focus-visible:after:scale-x-100';\n\nconst mobileLinkClassName =\n 'flex min-h-12 items-center rounded-control px-3 text-label font-semibold text-content-secondary transition-colors duration-200 ease-brand hover:text-content-primary focus-visible:outline-none focus-visible:shadow-focus';\n\nexport function Navbar({\n actions,\n brand,\n items,\n layer = 'standard',\n linkTreatment = 'plain',\n linkWeight = 'semibold',\n mobileNavigation,\n navigationLabel,\n renderLink,\n width = 'content',\n}: NavbarProps) {\n const mobileNavigationReference = useId();\n const mobileNavigationId = `navbar-mobile-navigation-${mobileNavigationReference}`;\n const mobileNavigationAnchorName = `--navbar-mobile-menu-trigger-${mobileNavigationReference.replace(/[^a-zA-Z0-9_-]/g, '-')}`;\n const linkClassName = [\n baseLinkClassName,\n linkWeight === 'bold' ? 'font-bold' : 'font-semibold',\n linkTreatment === 'underlined' ? underlinedLinkClassName : '',\n ]\n .filter(Boolean)\n .join(' ');\n const containerWidthClassName = width === 'wide' ? 'max-w-7xl' : 'max-w-5xl';\n const layerClassName = layer === 'above' ? 'z-50' : 'z-40';\n const renderLinks = (className: string) =>\n items.map((item) => (\n <Fragment key={item.href}>\n {renderLink ? (\n renderLink({\n children: item.label,\n className,\n href: item.href,\n })\n ) : (\n <a className={className} href={item.href}>\n {item.label}\n </a>\n )}\n </Fragment>\n ));\n\n return (\n <header\n className={`sticky top-0 ${layerClassName} border-b border-border-subtle bg-surface-page/90 text-label font-semibold backdrop-blur-lg`}\n >\n <div\n className={`mx-auto flex min-h-20 ${containerWidthClassName} items-center justify-between gap-4 px-shell`}\n >\n <div className=\"shrink-0\">{brand}</div>\n <nav aria-label={navigationLabel} className=\"hidden items-center gap-6 lg:flex\">\n {renderLinks(linkClassName)}\n </nav>\n {actions}\n {mobileNavigation ? (\n <div className=\"relative md:hidden\">\n <button\n aria-controls={mobileNavigationId}\n aria-label={mobileNavigation.menuLabel}\n className=\"flex size-12 cursor-pointer items-center justify-center rounded-control bg-action-primary text-content-inverse shadow-card transition-[translate,scale,background-color] duration-200 ease-brand active:scale-[0.97] focus-visible:outline-none focus-visible:shadow-focus\"\n popoverTarget={mobileNavigationId}\n popoverTargetAction=\"toggle\"\n style={{anchorName: mobileNavigationAnchorName}}\n type=\"button\"\n >\n <span className=\"sr-only\">{mobileNavigation.menuLabel}</span>\n <LuMenu aria-hidden=\"true\" className=\"size-6\" />\n </button>\n <nav\n aria-label={mobileNavigation.navigationLabel}\n className=\"fixed top-[4.5rem] right-[1.25rem] m-0 w-72 rounded-card border border-border-subtle bg-surface-raised p-3 shadow-float [@supports(position-anchor:--navbar-mobile-menu-trigger)]:absolute [@supports(position-anchor:--navbar-mobile-menu-trigger)]:top-[calc(anchor(bottom)+0.5rem)] [@supports(position-anchor:--navbar-mobile-menu-trigger)]:right-auto [@supports(position-anchor:--navbar-mobile-menu-trigger)]:left-[anchor(right)] [@supports(position-anchor:--navbar-mobile-menu-trigger)]:-translate-x-full\"\n id={mobileNavigationId}\n popover=\"auto\"\n style={{positionAnchor: mobileNavigationAnchorName}}\n >\n {renderLinks(mobileLinkClassName)}\n {mobileNavigation.actions ? (\n <div className=\"mt-2 space-y-3 border-t border-border-subtle pt-3\">\n {mobileNavigation.actions}\n </div>\n ) : null}\n </nav>\n </div>\n ) : null}\n </div>\n </header>\n );\n}\n"],"mappings":"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","names":["jsx","jsxs","jsx","jsxs","useId","jsx","jsxs"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1e99/components",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Reusable React components built with Tailwind CSS.",
5
5
  "repository": {
6
6
  "type": "git",