@devalok/shilp-sutra 0.56.0 → 0.59.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/MIGRATION.md +198 -0
- package/dist/_chunks/badge-group.js +75 -174
- package/dist/_chunks/badge-group.js.map +1 -1
- package/dist/_chunks/chat.js +270 -253
- package/dist/_chunks/chat.js.map +1 -1
- package/dist/_chunks/document-preview.js +1 -1
- package/dist/_chunks/document-preview.js.map +1 -1
- package/dist/_chunks/emoji-suggestion.js +1 -1
- package/dist/_chunks/emoji-suggestion.js.map +1 -1
- package/dist/_chunks/image-preview.js +71 -70
- package/dist/_chunks/image-preview.js.map +1 -1
- package/dist/_chunks/mention-suggestion.js +2 -2
- package/dist/_chunks/mention-suggestion.js.map +1 -1
- package/dist/_chunks/motion-preference.js +15 -0
- package/dist/_chunks/motion-preference.js.map +1 -0
- package/dist/_chunks/motion-provider.js +1 -1
- package/dist/_chunks/motion-provider.js.map +1 -1
- package/dist/_chunks/oauth-button.js +1 -1
- package/dist/_chunks/oauth-button.js.map +1 -1
- package/dist/_chunks/popover.js +50 -49
- package/dist/_chunks/popover.js.map +1 -1
- package/dist/_chunks/primitives-internal.js +29 -29
- package/dist/_chunks/primitives-internal.js.map +1 -1
- package/dist/_chunks/shared.js +48 -47
- package/dist/_chunks/shared.js.map +1 -1
- package/dist/_chunks/success.js +36 -36
- package/dist/_chunks/success.js.map +1 -1
- package/dist/_chunks/tree-view.js +1 -1
- package/dist/_chunks/tree-view.js.map +1 -1
- package/dist/_chunks/use-calendar.js +4 -4
- package/dist/_chunks/use-calendar.js.map +1 -1
- package/dist/ai/block-renderer.js +8 -8
- package/dist/ai/blocks/text.js +1 -1
- package/dist/ai/blocks/text.js.map +1 -1
- package/dist/ai/command-bar.js +67 -67
- package/dist/ai/command-bar.js.map +1 -1
- package/dist/ai/conversation.js +35 -35
- package/dist/ai/conversation.js.map +1 -1
- package/dist/ai/index.js +4 -4
- package/dist/composed/activity-feed.d.ts.map +1 -1
- package/dist/composed/activity-feed.js +109 -108
- package/dist/composed/activity-feed.js.map +1 -1
- package/dist/composed/avatar-group.d.ts +7 -2
- package/dist/composed/avatar-group.d.ts.map +1 -1
- package/dist/composed/avatar-group.js +3 -3
- package/dist/composed/avatar-group.js.map +1 -1
- package/dist/composed/command-palette.js +137 -137
- package/dist/composed/command-palette.js.map +1 -1
- package/dist/composed/content-card.js +2 -2
- package/dist/composed/content-card.js.map +1 -1
- package/dist/composed/date-picker/index.js +9 -9
- package/dist/composed/date-picker/index.js.map +1 -1
- package/dist/composed/diff.d.ts +23 -2
- package/dist/composed/diff.d.ts.map +1 -1
- package/dist/composed/diff.js +341 -260
- package/dist/composed/diff.js.map +1 -1
- package/dist/composed/emoji-picker.js +3 -3
- package/dist/composed/emoji-picker.js.map +1 -1
- package/dist/composed/empty-state.js +4 -4
- package/dist/composed/error-boundary.js +2 -2
- package/dist/composed/error-boundary.js.map +1 -1
- package/dist/composed/file-preview/image-preview.d.ts.map +1 -1
- package/dist/composed/file-preview/shared.d.ts.map +1 -1
- package/dist/composed/file-preview/video-preview.d.ts.map +1 -1
- package/dist/composed/file-preview.js +152 -151
- package/dist/composed/file-preview.js.map +1 -1
- package/dist/composed/filter-bar.d.ts.map +1 -1
- package/dist/composed/filter-bar.js +53 -52
- package/dist/composed/filter-bar.js.map +1 -1
- package/dist/composed/form-section.d.ts.map +1 -1
- package/dist/composed/form-section.js +38 -37
- package/dist/composed/form-section.js.map +1 -1
- package/dist/composed/inline-edit.js +1 -1
- package/dist/composed/inline-edit.js.map +1 -1
- package/dist/composed/loading-skeleton.js +3 -3
- package/dist/composed/loading-skeleton.js.map +1 -1
- package/dist/composed/master-detail.d.ts.map +1 -1
- package/dist/composed/master-detail.js +1 -1
- package/dist/composed/master-detail.js.map +1 -1
- package/dist/composed/member-picker.js +1 -1
- package/dist/composed/member-picker.js.map +1 -1
- package/dist/composed/multi-select-popover.d.ts.map +1 -1
- package/dist/composed/multi-select-popover.js +109 -108
- package/dist/composed/multi-select-popover.js.map +1 -1
- package/dist/composed/page-skeletons.js +4 -4
- package/dist/composed/page-skeletons.js.map +1 -1
- package/dist/composed/responsive-modal.js +1 -1
- package/dist/composed/responsive-modal.js.map +1 -1
- package/dist/composed/rich-chat-input/attachment-strip.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/reply-banner.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/schedule-send.d.ts.map +1 -1
- package/dist/composed/rich-chat-input.d.ts.map +1 -1
- package/dist/composed/rich-chat-input.js +473 -472
- package/dist/composed/rich-chat-input.js.map +1 -1
- package/dist/composed/rich-text-editor.js +6 -6
- package/dist/composed/rich-text-editor.js.map +1 -1
- package/dist/composed/schedule-view.js +5 -5
- package/dist/composed/schedule-view.js.map +1 -1
- package/dist/composed/status-badge.d.ts.map +1 -1
- package/dist/composed/status-badge.js +29 -28
- package/dist/composed/status-badge.js.map +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +4 -3
- package/dist/hooks/use-container-size.d.ts +18 -0
- package/dist/hooks/use-container-size.d.ts.map +1 -0
- package/dist/hooks/use-container-size.js +28 -0
- package/dist/hooks/use-container-size.js.map +1 -0
- package/dist/motion/index.d.ts +1 -0
- package/dist/motion/index.d.ts.map +1 -1
- package/dist/motion/index.js +2 -15
- package/dist/motion/motion-preference.d.ts +36 -0
- package/dist/motion/motion-preference.d.ts.map +1 -0
- package/dist/motion/motion-provider.d.ts +2 -1
- package/dist/motion/motion-provider.d.ts.map +1 -1
- package/dist/motion/primitives-index.js +103 -102
- package/dist/motion/primitives-index.js.map +1 -1
- package/dist/motion/primitives.d.ts.map +1 -1
- package/dist/shell/app-shell.d.ts +101 -0
- package/dist/shell/app-shell.d.ts.map +1 -0
- package/dist/shell/app-shell.js +76 -0
- package/dist/shell/app-shell.js.map +1 -0
- package/dist/shell/bottom-navbar.js +21 -21
- package/dist/shell/bottom-navbar.js.map +1 -1
- package/dist/shell/index.d.ts +2 -1
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +6 -5
- package/dist/shell/notification-center.d.ts +17 -0
- package/dist/shell/notification-center.d.ts.map +1 -1
- package/dist/shell/notification-center.js +110 -105
- package/dist/shell/notification-center.js.map +1 -1
- package/dist/shell/notification-preferences.js +1 -1
- package/dist/shell/notification-preferences.js.map +1 -1
- package/dist/shell/top-bar.js +7 -7
- package/dist/shell/top-bar.js.map +1 -1
- package/dist/tokens/generate-scale.d.ts +49 -0
- package/dist/tokens/generate-scale.d.ts.map +1 -1
- package/dist/tokens/index.css +1 -0
- package/dist/tokens/palettes.css +292 -0
- package/dist/tokens/primitives.css +29 -26
- package/dist/tokens/semantic.css +170 -47
- package/dist/tokens/shilp-sutra.css +1 -0
- package/dist/tokens/utilities.css +10 -7
- package/dist/tokens/variants.css +1 -1
- package/dist/ui/accordion.d.ts.map +1 -1
- package/dist/ui/accordion.js +27 -26
- package/dist/ui/accordion.js.map +1 -1
- package/dist/ui/alert-dialog.d.ts.map +1 -1
- package/dist/ui/alert-dialog.js +60 -59
- package/dist/ui/alert-dialog.js.map +1 -1
- package/dist/ui/alert.d.ts.map +1 -1
- package/dist/ui/alert.js +55 -113
- package/dist/ui/alert.js.map +1 -1
- package/dist/ui/autocomplete.js +80 -80
- package/dist/ui/autocomplete.js.map +1 -1
- package/dist/ui/avatar.d.ts.map +1 -1
- package/dist/ui/avatar.js +71 -70
- package/dist/ui/avatar.js.map +1 -1
- package/dist/ui/badge-indicator.d.ts +4 -8
- package/dist/ui/badge-indicator.d.ts.map +1 -1
- package/dist/ui/badge-indicator.js +3 -8
- package/dist/ui/badge-indicator.js.map +1 -1
- package/dist/ui/badge.d.ts +55 -34
- package/dist/ui/badge.d.ts.map +1 -1
- package/dist/ui/banner.d.ts.map +1 -1
- package/dist/ui/banner.js +43 -41
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/button-group.d.ts.map +1 -1
- package/dist/ui/button-group.js +3 -23
- package/dist/ui/button-group.js.map +1 -1
- package/dist/ui/button.d.ts +10 -1
- package/dist/ui/button.d.ts.map +1 -1
- package/dist/ui/button.js +79 -212
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/card.d.ts.map +1 -1
- package/dist/ui/card.js +78 -75
- package/dist/ui/card.js.map +1 -1
- package/dist/ui/charts/radar-chart.d.ts.map +1 -1
- package/dist/ui/charts/radar-chart.js +1 -1
- package/dist/ui/charts/radar-chart.js.map +1 -1
- package/dist/ui/chat/date-separator.d.ts +8 -1
- package/dist/ui/chat/date-separator.d.ts.map +1 -1
- package/dist/ui/chat/message-list.d.ts.map +1 -1
- package/dist/ui/chat/message.d.ts.map +1 -1
- package/dist/ui/chat/typing-indicator.d.ts.map +1 -1
- package/dist/ui/checkbox.js +1 -1
- package/dist/ui/checkbox.js.map +1 -1
- package/dist/ui/code.js +2 -2
- package/dist/ui/code.js.map +1 -1
- package/dist/ui/color-input.d.ts.map +1 -1
- package/dist/ui/color-input.js +151 -150
- package/dist/ui/color-input.js.map +1 -1
- package/dist/ui/combobox.d.ts +14 -0
- package/dist/ui/combobox.d.ts.map +1 -1
- package/dist/ui/combobox.js +156 -152
- package/dist/ui/combobox.js.map +1 -1
- package/dist/ui/context-menu.d.ts.map +1 -1
- package/dist/ui/context-menu.js +70 -69
- package/dist/ui/context-menu.js.map +1 -1
- package/dist/ui/data-table-body.d.ts +3 -1
- package/dist/ui/data-table-body.d.ts.map +1 -1
- package/dist/ui/data-table-body.js +93 -92
- package/dist/ui/data-table-body.js.map +1 -1
- package/dist/ui/data-table-bulk-actions.d.ts +7 -1
- package/dist/ui/data-table-bulk-actions.d.ts.map +1 -1
- package/dist/ui/data-table-bulk-actions.js +14 -8
- package/dist/ui/data-table-bulk-actions.js.map +1 -1
- package/dist/ui/data-table-card.d.ts.map +1 -1
- package/dist/ui/data-table-card.js +66 -47
- package/dist/ui/data-table-card.js.map +1 -1
- package/dist/ui/data-table-context.d.ts +4 -0
- package/dist/ui/data-table-context.d.ts.map +1 -1
- package/dist/ui/data-table-context.js +2 -2
- package/dist/ui/data-table-context.js.map +1 -1
- package/dist/ui/data-table-header.d.ts.map +1 -1
- package/dist/ui/data-table-header.js +50 -46
- package/dist/ui/data-table-header.js.map +1 -1
- package/dist/ui/data-table-pagination.js +3 -3
- package/dist/ui/data-table-pagination.js.map +1 -1
- package/dist/ui/data-table-toolbar.d.ts +11 -1
- package/dist/ui/data-table-toolbar.d.ts.map +1 -1
- package/dist/ui/data-table-toolbar.js +7 -7
- package/dist/ui/data-table-toolbar.js.map +1 -1
- package/dist/ui/data-table.d.ts +52 -5
- package/dist/ui/data-table.d.ts.map +1 -1
- package/dist/ui/data-table.js +181 -169
- package/dist/ui/data-table.js.map +1 -1
- package/dist/ui/dialog.d.ts.map +1 -1
- package/dist/ui/dialog.js +62 -61
- package/dist/ui/dialog.js.map +1 -1
- package/dist/ui/dot.d.ts.map +1 -1
- package/dist/ui/dot.js +10 -41
- package/dist/ui/dot.js.map +1 -1
- package/dist/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/ui/dropdown-menu.js +79 -78
- package/dist/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/file-upload.d.ts.map +1 -1
- package/dist/ui/file-upload.js +117 -116
- package/dist/ui/file-upload.js.map +1 -1
- package/dist/ui/form.d.ts.map +1 -1
- package/dist/ui/form.js +27 -26
- package/dist/ui/form.js.map +1 -1
- package/dist/ui/hover-card.d.ts.map +1 -1
- package/dist/ui/hover-card.js +26 -25
- package/dist/ui/hover-card.js.map +1 -1
- package/dist/ui/icon.js +7 -7
- package/dist/ui/index.d.ts +2 -2
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +3 -3
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/input-otp.js +1 -1
- package/dist/ui/input-otp.js.map +1 -1
- package/dist/ui/input.js +8 -8
- package/dist/ui/input.js.map +1 -1
- package/dist/ui/menubar.d.ts.map +1 -1
- package/dist/ui/menubar.js +73 -72
- package/dist/ui/menubar.js.map +1 -1
- package/dist/ui/navigation-menu.d.ts.map +1 -1
- package/dist/ui/navigation-menu.js +80 -79
- package/dist/ui/navigation-menu.js.map +1 -1
- package/dist/ui/number-input.js +3 -3
- package/dist/ui/number-input.js.map +1 -1
- package/dist/ui/pagination.js +1 -1
- package/dist/ui/pagination.js.map +1 -1
- package/dist/ui/popover.d.ts.map +1 -1
- package/dist/ui/progress-ring.js +2 -2
- package/dist/ui/progress-ring.js.map +1 -1
- package/dist/ui/progress.d.ts.map +1 -1
- package/dist/ui/progress.js +82 -74
- package/dist/ui/progress.js.map +1 -1
- package/dist/ui/radio.d.ts.map +1 -1
- package/dist/ui/radio.js +32 -31
- package/dist/ui/radio.js.map +1 -1
- package/dist/ui/search-input.d.ts.map +1 -1
- package/dist/ui/search-input.js +28 -27
- package/dist/ui/search-input.js.map +1 -1
- package/dist/ui/select.d.ts.map +1 -1
- package/dist/ui/select.js +67 -66
- package/dist/ui/select.js.map +1 -1
- package/dist/ui/sheet.js +1 -1
- package/dist/ui/sheet.js.map +1 -1
- package/dist/ui/sidebar.d.ts.map +1 -1
- package/dist/ui/sidebar.js +14 -14
- package/dist/ui/sidebar.js.map +1 -1
- package/dist/ui/slider.d.ts +63 -9
- package/dist/ui/slider.d.ts.map +1 -1
- package/dist/ui/slider.js +75 -33
- package/dist/ui/slider.js.map +1 -1
- package/dist/ui/split-button.d.ts +8 -2
- package/dist/ui/split-button.d.ts.map +1 -1
- package/dist/ui/split-button.js +49 -95
- package/dist/ui/split-button.js.map +1 -1
- package/dist/ui/stat-card.d.ts.map +1 -1
- package/dist/ui/stat-card.js +89 -88
- package/dist/ui/stat-card.js.map +1 -1
- package/dist/ui/stat-flash.js +16 -16
- package/dist/ui/stepper.d.ts.map +1 -1
- package/dist/ui/stepper.js +63 -62
- package/dist/ui/stepper.js.map +1 -1
- package/dist/ui/surface.d.ts.map +1 -1
- package/dist/ui/surface.js +2 -2
- package/dist/ui/surface.js.map +1 -1
- package/dist/ui/switch.js +1 -1
- package/dist/ui/switch.js.map +1 -1
- package/dist/ui/table.js +3 -3
- package/dist/ui/table.js.map +1 -1
- package/dist/ui/tabs.d.ts.map +1 -1
- package/dist/ui/tabs.js +68 -67
- package/dist/ui/tabs.js.map +1 -1
- package/dist/ui/textarea.js +5 -5
- package/dist/ui/textarea.js.map +1 -1
- package/dist/ui/toast.d.ts.map +1 -1
- package/dist/ui/toast.js +196 -195
- package/dist/ui/toast.js.map +1 -1
- package/dist/ui/toggle.d.ts.map +1 -1
- package/dist/ui/toggle.js +26 -24
- package/dist/ui/toggle.js.map +1 -1
- package/dist/ui/tooltip.d.ts.map +1 -1
- package/dist/ui/tooltip.js +37 -36
- package/dist/ui/tooltip.js.map +1 -1
- package/dist/ui/tree-view/tree-item.d.ts.map +1 -1
- package/docs/components/composed/avatar-group.md +4 -4
- package/docs/components/composed/diff.md +10 -2
- package/docs/components/composed/schedule-view.md +1 -1
- package/docs/components/shell/app-shell.md +132 -0
- package/docs/components/ui/avatar.md +1 -1
- package/docs/components/ui/button.md +1 -1
- package/docs/components/ui/chat.md +7 -1
- package/docs/components/ui/color-swatch.md +1 -1
- package/docs/components/ui/data-table-toolbar.md +6 -2
- package/docs/components/ui/data-table.md +41 -7
- package/docs/components/ui/dot.md +1 -1
- package/docs/components/ui/progress.md +1 -0
- package/docs/components/ui/surface.md +3 -3
- package/docs/components/ui/table.md +2 -2
- package/docs/recipes/customize-brand.md +58 -0
- package/docs/recipes/install-astro.md +1 -0
- package/docs/recipes/install-next-app-router.md +1 -0
- package/docs/recipes/install-next-pages.md +22 -1
- package/docs/recipes/install-remix.md +1 -0
- package/docs/recipes/install-tanstack-start.md +1 -0
- package/docs/recipes/install-vite.md +2 -0
- package/docs/recipes/server-components.md +7 -4
- package/docs/recipes/troubleshoot.md +1 -0
- package/llms.txt +2 -1
- package/make-kit/Guidelines.md +2 -2
- package/make-kit/components/button.md +1 -1
- package/make-kit/components/card.md +6 -6
- package/make-kit/components/surface.md +4 -4
- package/make-kit/foundations/color.md +4 -4
- package/make-kit/foundations/dark-mode.md +1 -1
- package/make-kit/foundations/radius.md +1 -1
- package/make-kit/foundations/surfaces.md +9 -9
- package/mcp-manifest.json +358 -35
- package/package.json +8 -4
- package/skill/SKILL.md +12 -6
- package/skill/references/components.md +2 -1
- package/skill/references/customize-brand.md +58 -0
- package/skill/references/server-components.md +7 -4
- package/skill/references/setup-astro.md +1 -0
- package/skill/references/setup-next-app-router.md +1 -0
- package/skill/references/setup-next-pages.md +22 -1
- package/skill/references/setup-remix.md +1 -0
- package/skill/references/setup-tanstack-start.md +1 -0
- package/skill/references/setup-vite.md +2 -0
- package/skill/references/troubleshoot.md +1 -0
- package/dist/motion/check-motion-provider.d.ts +0 -2
- package/dist/motion/check-motion-provider.d.ts.map +0 -1
- package/dist/motion/index.js.map +0 -1
- package/dist/primitives/react-toast.d.ts +0 -120
- package/dist/ui/charts/_internal/scales.d.ts +0 -5
- package/dist/ui/charts/_internal/scales.d.ts.map +0 -1
- package/dist/ui/lib/slot.d.ts +0 -8
- package/dist/ui/lib/slot.d.ts.map +0 -1
package/dist/ui/autocomplete.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { autoUpdate as e, flip as t, offset as n, shift as
|
|
3
|
-
import { tweens as
|
|
2
|
+
import { autoUpdate as e, flip as t, offset as n, shift as ee, size as r, useFloating as i } from "../_chunks/primitives-internal.js";
|
|
3
|
+
import { tweens as a } from "./lib/motion.js";
|
|
4
|
+
import { useMotion as o } from "../_chunks/motion-provider.js";
|
|
4
5
|
import { cn as s } from "./lib/utils.js";
|
|
5
6
|
import { Spinner as c } from "./spinner.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { Input as ee } from "./input.js";
|
|
7
|
+
import { useFormField as l } from "./form.js";
|
|
8
|
+
import { Input as u } from "./input.js";
|
|
9
9
|
import * as d from "react";
|
|
10
10
|
import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
11
|
-
import { createPortal as
|
|
12
|
-
import { AnimatePresence as
|
|
11
|
+
import { createPortal as te } from "react-dom";
|
|
12
|
+
import { AnimatePresence as h, motion as g } from "framer-motion";
|
|
13
13
|
//#region src/ui/autocomplete.tsx
|
|
14
|
-
function
|
|
14
|
+
function _({ label: e, query: t }) {
|
|
15
15
|
let n = t ? e.toLowerCase().indexOf(t.toLowerCase()) : -1;
|
|
16
16
|
return n === -1 ? /* @__PURE__ */ p(f, { children: e }) : /* @__PURE__ */ m(f, { children: [
|
|
17
17
|
e.slice(0, n),
|
|
@@ -22,130 +22,130 @@ function v({ label: e, query: t }) {
|
|
|
22
22
|
e.slice(n + t.length)
|
|
23
23
|
] });
|
|
24
24
|
}
|
|
25
|
-
var
|
|
26
|
-
let
|
|
27
|
-
open:
|
|
25
|
+
var v = d.forwardRef(({ options: f, value: v, defaultValue: y = null, onValueChange: b, placeholder: x, emptyText: S = "No options", disabled: C, size: w, state: T, isLoading: E = !1, loadingText: D = "Loading…", renderOption: O, className: k, id: A, ...ne }, j) => {
|
|
26
|
+
let M = d.useId(), N = A || M, P = `${N}-listbox`, F = `${N}-option`, I = v !== void 0, [L, R] = d.useState(y), z = I ? v : L, [B, V] = d.useState(z?.label ?? ""), [H, U] = d.useState(!1), [W, G] = d.useState(-1), K = d.useRef(null), q = d.useRef(null), J = d.useRef(null), { reducedMotion: Y } = o(), { refs: X, floatingStyles: re } = i({
|
|
27
|
+
open: H,
|
|
28
28
|
placement: "bottom-start",
|
|
29
29
|
whileElementsMounted: e,
|
|
30
30
|
middleware: [
|
|
31
31
|
n(4),
|
|
32
32
|
t(),
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
ee(),
|
|
34
|
+
r({ apply({ availableHeight: e, rects: t, elements: n }) {
|
|
35
35
|
Object.assign(n.floating.style, {
|
|
36
36
|
maxHeight: `${Math.min(e, 240)}px`,
|
|
37
37
|
width: `${t.reference.width}px`
|
|
38
38
|
});
|
|
39
39
|
} })
|
|
40
40
|
]
|
|
41
|
-
}),
|
|
42
|
-
|
|
43
|
-
}, [
|
|
44
|
-
|
|
45
|
-
}, [
|
|
46
|
-
|
|
47
|
-
}, [
|
|
41
|
+
}), ie = d.useCallback((e) => {
|
|
42
|
+
q.current = e, X.setReference(e);
|
|
43
|
+
}, [X]), ae = d.useCallback((e) => {
|
|
44
|
+
K.current = e, typeof j == "function" ? j(e) : j && (j.current = e);
|
|
45
|
+
}, [j]), oe = d.useCallback((e) => {
|
|
46
|
+
J.current = e, X.setFloating(e);
|
|
47
|
+
}, [X]);
|
|
48
48
|
d.useEffect(() => {
|
|
49
|
-
|
|
50
|
-
}, [
|
|
51
|
-
let
|
|
52
|
-
|
|
53
|
-
}, [
|
|
54
|
-
if (!
|
|
55
|
-
if (!
|
|
56
|
-
(e.key === "ArrowDown" || e.key === "Enter") &&
|
|
49
|
+
V(z?.label ?? "");
|
|
50
|
+
}, [z]);
|
|
51
|
+
let Z = d.useMemo(() => B ? f.filter((e) => e.label.toLowerCase().includes(B.toLowerCase())) : f, [f, B]), Q = d.useCallback((e) => {
|
|
52
|
+
V(e.label), U(!1), G(-1), I || R(e), b?.(e);
|
|
53
|
+
}, [I, b]), $ = d.useCallback((e) => {
|
|
54
|
+
if (!C) {
|
|
55
|
+
if (!H) {
|
|
56
|
+
(e.key === "ArrowDown" || e.key === "Enter") && U(!0);
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
59
|
switch (e.key) {
|
|
60
60
|
case "ArrowDown":
|
|
61
|
-
e.preventDefault(),
|
|
61
|
+
e.preventDefault(), G((e) => Math.min(e + 1, Z.length - 1));
|
|
62
62
|
break;
|
|
63
63
|
case "ArrowUp":
|
|
64
|
-
e.preventDefault(),
|
|
64
|
+
e.preventDefault(), G((e) => Math.max(e - 1, 0));
|
|
65
65
|
break;
|
|
66
66
|
case "Home":
|
|
67
|
-
e.preventDefault(),
|
|
67
|
+
e.preventDefault(), G(0);
|
|
68
68
|
break;
|
|
69
69
|
case "End":
|
|
70
|
-
e.preventDefault(),
|
|
70
|
+
e.preventDefault(), G(Z.length - 1);
|
|
71
71
|
break;
|
|
72
72
|
case "Enter":
|
|
73
|
-
e.preventDefault(),
|
|
73
|
+
e.preventDefault(), W >= 0 && Z[W] && Q(Z[W]);
|
|
74
74
|
break;
|
|
75
75
|
case "Escape":
|
|
76
|
-
|
|
76
|
+
U(!1), G(-1);
|
|
77
77
|
break;
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
}, [
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
]), se =
|
|
81
|
+
C,
|
|
82
|
+
H,
|
|
83
|
+
Z,
|
|
84
|
+
W,
|
|
85
|
+
Q
|
|
86
|
+
]), se = l(), ce = !!(A || se.inputId), le = W >= 0 ? `${F}-${W}` : void 0;
|
|
87
87
|
return /* @__PURE__ */ m("div", {
|
|
88
|
-
ref:
|
|
89
|
-
className: s("relative",
|
|
90
|
-
...
|
|
91
|
-
children: [/* @__PURE__ */ p(
|
|
92
|
-
ref:
|
|
88
|
+
ref: ie,
|
|
89
|
+
className: s("relative", k),
|
|
90
|
+
...ne,
|
|
91
|
+
children: [/* @__PURE__ */ p(u, {
|
|
92
|
+
ref: ae,
|
|
93
93
|
type: "text",
|
|
94
94
|
role: "combobox",
|
|
95
|
-
size:
|
|
96
|
-
state:
|
|
97
|
-
id:
|
|
98
|
-
value:
|
|
99
|
-
placeholder:
|
|
100
|
-
disabled:
|
|
101
|
-
"aria-expanded":
|
|
95
|
+
size: w,
|
|
96
|
+
state: T,
|
|
97
|
+
id: A,
|
|
98
|
+
value: B,
|
|
99
|
+
placeholder: x,
|
|
100
|
+
disabled: C,
|
|
101
|
+
"aria-expanded": H,
|
|
102
102
|
"aria-autocomplete": "list",
|
|
103
|
-
"aria-controls":
|
|
103
|
+
"aria-controls": H ? P : void 0,
|
|
104
104
|
"aria-activedescendant": le,
|
|
105
|
-
"aria-label": ce ? void 0 :
|
|
106
|
-
endSection:
|
|
105
|
+
"aria-label": ce ? void 0 : x,
|
|
106
|
+
endSection: E ? /* @__PURE__ */ p(c, { size: "sm" }) : void 0,
|
|
107
107
|
onChange: (e) => {
|
|
108
|
-
|
|
108
|
+
V(e.target.value), U(!0), G(-1);
|
|
109
109
|
},
|
|
110
|
-
onFocus: () =>
|
|
110
|
+
onFocus: () => U(!0),
|
|
111
111
|
onBlur: (e) => {
|
|
112
112
|
let t = e.relatedTarget;
|
|
113
|
-
!
|
|
113
|
+
!q.current?.contains(t) && !J.current?.contains(t) && U(!1);
|
|
114
114
|
},
|
|
115
|
-
onKeyDown:
|
|
116
|
-
}), typeof document < "u" &&
|
|
117
|
-
id:
|
|
118
|
-
ref:
|
|
115
|
+
onKeyDown: $
|
|
116
|
+
}), typeof document < "u" && te(/* @__PURE__ */ p(h, { children: H && /* @__PURE__ */ p(g.ul, {
|
|
117
|
+
id: P,
|
|
118
|
+
ref: oe,
|
|
119
119
|
role: "listbox",
|
|
120
|
-
initial: !
|
|
120
|
+
initial: !Y && { opacity: 0 },
|
|
121
121
|
animate: { opacity: 1 },
|
|
122
|
-
exit:
|
|
123
|
-
transition:
|
|
124
|
-
style:
|
|
122
|
+
exit: Y ? { opacity: 1 } : { opacity: 0 },
|
|
123
|
+
transition: Y ? { duration: 0 } : a.fade,
|
|
124
|
+
style: re,
|
|
125
125
|
className: "z-popover overflow-auto rounded-overlay bg-surface-overlay shadow-raised-hover",
|
|
126
|
-
children:
|
|
126
|
+
children: E ? /* @__PURE__ */ m("li", {
|
|
127
127
|
className: "flex items-center gap-ds-03 px-ds-04 py-ds-03 text-body-md text-surface-fg-muted",
|
|
128
|
-
children: [/* @__PURE__ */ p(c, { size: "sm" }),
|
|
129
|
-
}) :
|
|
128
|
+
children: [/* @__PURE__ */ p(c, { size: "sm" }), D]
|
|
129
|
+
}) : Z.length === 0 ? /* @__PURE__ */ p("li", {
|
|
130
130
|
className: "px-ds-04 py-ds-03 text-body-md text-surface-fg-muted",
|
|
131
|
-
children:
|
|
132
|
-
}) :
|
|
133
|
-
id: `${
|
|
131
|
+
children: S
|
|
132
|
+
}) : Z.map((e, t) => /* @__PURE__ */ p("li", {
|
|
133
|
+
id: `${F}-${t}`,
|
|
134
134
|
role: "option",
|
|
135
|
-
"aria-selected":
|
|
135
|
+
"aria-selected": W === t,
|
|
136
136
|
title: e.label,
|
|
137
|
-
className: s("cursor-pointer truncate px-ds-04 py-ds-03 text-body-md text-surface-fg transition-colors duration-fast-01",
|
|
137
|
+
className: s("cursor-pointer truncate px-ds-04 py-ds-03 text-body-md text-surface-fg transition-colors duration-fast-01", W === t && "bg-accent-4", z?.value === e.value && "font-semibold"),
|
|
138
138
|
onMouseDown: (e) => e.preventDefault(),
|
|
139
|
-
onClick: () =>
|
|
140
|
-
onMouseEnter: () =>
|
|
141
|
-
children:
|
|
139
|
+
onClick: () => Q(e),
|
|
140
|
+
onMouseEnter: () => G(t),
|
|
141
|
+
children: O ? O(e, B) : /* @__PURE__ */ p(_, {
|
|
142
142
|
label: e.label,
|
|
143
|
-
query:
|
|
143
|
+
query: B
|
|
144
144
|
})
|
|
145
145
|
}, e.value))
|
|
146
146
|
}) }), document.body)]
|
|
147
147
|
});
|
|
148
148
|
});
|
|
149
|
-
|
|
149
|
+
v.displayName = "Autocomplete";
|
|
150
150
|
//#endregion
|
|
151
|
-
export {
|
|
151
|
+
export { v as Autocomplete };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autocomplete.js","names":[],"sources":["../../src/ui/autocomplete.tsx"],"sourcesContent":["'use client'\n\nimport { autoUpdate, flip, offset, shift, size as sizeMiddleware, useFloating } from '@floating-ui/react-dom'\nimport { AnimatePresence, motion } from 'framer-motion'\nimport * as React from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { useMotion } from '../motion/motion-provider'\nimport { useFormField } from './form'\nimport { Input, type InputProps } from './input'\nimport { tweens } from './lib/motion'\nimport { cn } from './lib/utils'\nimport { Spinner } from './spinner'\n\nexport type AutocompleteOption = {\n label: string\n value: string\n}\n\n/**\n * A free-text input with a live-filtered dropdown, keyboard navigation, and\n * combobox ARIA. The field itself is the DS `Input`, so it inherits size,\n * error/state painting, read-only, hover, and FormField wiring.\n *\n * Free-text (no forced selection) — for enforced selection use `Combobox`.\n * `value`/`defaultValue` are a full `AutocompleteOption` (or null).\n */\nexport type AutocompleteProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> & {\n options: AutocompleteOption[]\n /** Controlled selection. */\n value?: AutocompleteOption | null\n /** Initial selection for uncontrolled mode. */\n defaultValue?: AutocompleteOption | null\n onValueChange?: (option: AutocompleteOption) => void\n placeholder?: string\n emptyText?: string\n disabled?: boolean\n /** Input size (forwarded to the composed `Input`). */\n size?: InputProps['size']\n /** Field state (forwarded to `Input`); overrides FormField auto-consumption. */\n state?: InputProps['state']\n /** Show a loading spinner + `loadingText` (async \"type to search\"). */\n isLoading?: boolean\n loadingText?: string\n /** Custom option renderer. Receives the option and the current query. */\n renderOption?: (option: AutocompleteOption, query: string) => React.ReactNode\n className?: string\n id?: string\n}\n\n/** Bold the matched substring inside an option label. */\nfunction HighlightMatch({ label, query }: { label: string; query: string }) {\n const idx = query ? label.toLowerCase().indexOf(query.toLowerCase()) : -1\n if (idx === -1) return <>{label}</>\n return (\n <>\n {label.slice(0, idx)}\n <span className=\"font-semibold text-accent-11\">{label.slice(idx, idx + query.length)}</span>\n {label.slice(idx + query.length)}\n </>\n )\n}\n\nconst Autocomplete = React.forwardRef<HTMLInputElement, AutocompleteProps>(\n (\n {\n options,\n value,\n defaultValue = null,\n onValueChange,\n placeholder,\n emptyText = 'No options',\n disabled,\n size,\n state,\n isLoading = false,\n loadingText = 'Loading…',\n renderOption,\n className,\n id: externalId,\n ...props\n },\n ref,\n ) => {\n const internalId = React.useId()\n const baseId = externalId || internalId\n const listboxId = `${baseId}-listbox`\n const optionIdPrefix = `${baseId}-option`\n\n // Controlled / uncontrolled selection\n const isControlled = value !== undefined\n const [internalValue, setInternalValue] = React.useState<AutocompleteOption | null>(defaultValue)\n const selected = isControlled ? value : internalValue\n\n const [query, setQuery] = React.useState(selected?.label ?? '')\n const [isOpen, setIsOpen] = React.useState(false)\n const [highlightedIndex, setHighlightedIndex] = React.useState(-1)\n const internalRef = React.useRef<HTMLInputElement>(null)\n const containerRef = React.useRef<HTMLDivElement>(null)\n const floatingRef = React.useRef<HTMLUListElement>(null)\n const { reducedMotion } = useMotion()\n\n // Floating UI — anchor the dropdown to the whole field (container width)\n const { refs, floatingStyles } = useFloating({\n open: isOpen,\n placement: 'bottom-start',\n whileElementsMounted: autoUpdate,\n middleware: [\n offset(4),\n flip(),\n shift(),\n sizeMiddleware({\n apply({ availableHeight, rects, elements }) {\n Object.assign(elements.floating.style, {\n maxHeight: `${Math.min(availableHeight, 240)}px`,\n width: `${rects.reference.width}px`,\n })\n },\n }),\n ],\n })\n\n const setContainer = React.useCallback(\n (node: HTMLDivElement | null) => {\n containerRef.current = node\n refs.setReference(node)\n },\n [refs],\n )\n\n const composedInputRef = React.useCallback(\n (node: HTMLInputElement | null) => {\n internalRef.current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLInputElement | null>).current = node\n },\n [ref],\n )\n\n const setFloating = React.useCallback(\n (node: HTMLUListElement | null) => {\n floatingRef.current = node\n refs.setFloating(node)\n },\n [refs],\n )\n\n // Sync query when the selection changes externally\n React.useEffect(() => {\n setQuery(selected?.label ?? '')\n }, [selected])\n\n const filtered = React.useMemo(\n () =>\n query\n ? options.filter((o) => o.label.toLowerCase().includes(query.toLowerCase()))\n : options,\n [options, query],\n )\n\n const handleSelect = React.useCallback(\n (option: AutocompleteOption) => {\n setQuery(option.label)\n setIsOpen(false)\n setHighlightedIndex(-1)\n if (!isControlled) setInternalValue(option)\n onValueChange?.(option)\n },\n [isControlled, onValueChange],\n )\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent) => {\n if (disabled) return\n if (!isOpen) {\n if (e.key === 'ArrowDown' || e.key === 'Enter') setIsOpen(true)\n return\n }\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n setHighlightedIndex((i) => Math.min(i + 1, filtered.length - 1))\n break\n case 'ArrowUp':\n e.preventDefault()\n setHighlightedIndex((i) => Math.max(i - 1, 0))\n break\n case 'Home':\n e.preventDefault()\n setHighlightedIndex(0)\n break\n case 'End':\n e.preventDefault()\n setHighlightedIndex(filtered.length - 1)\n break\n case 'Enter':\n e.preventDefault()\n if (highlightedIndex >= 0 && filtered[highlightedIndex]) handleSelect(filtered[highlightedIndex])\n break\n case 'Escape':\n setIsOpen(false)\n setHighlightedIndex(-1)\n break\n }\n },\n [disabled, isOpen, filtered, highlightedIndex, handleSelect],\n )\n\n // FormField wiring is auto-consumed by Input; only used here to decide the\n // standalone accessible-name fallback + the combobox aria-controls id.\n const fieldCtx = useFormField()\n const hasFieldName = !!(externalId || fieldCtx.inputId)\n const highlightedOptionId = highlightedIndex >= 0 ? `${optionIdPrefix}-${highlightedIndex}` : undefined\n\n return (\n <div ref={setContainer} className={cn('relative', className)} {...props}>\n <Input\n ref={composedInputRef}\n type=\"text\"\n role=\"combobox\"\n size={size}\n state={state}\n id={externalId}\n value={query}\n placeholder={placeholder}\n disabled={disabled}\n aria-expanded={isOpen}\n aria-autocomplete=\"list\"\n aria-controls={isOpen ? listboxId : undefined}\n aria-activedescendant={highlightedOptionId}\n aria-label={hasFieldName ? undefined : placeholder}\n endSection={isLoading ? <Spinner size=\"sm\" /> : undefined}\n onChange={(e) => {\n setQuery(e.target.value)\n setIsOpen(true)\n setHighlightedIndex(-1)\n }}\n onFocus={() => setIsOpen(true)}\n onBlur={(e) => {\n const target = e.relatedTarget as Node | null\n if (!containerRef.current?.contains(target) && !floatingRef.current?.contains(target)) {\n setIsOpen(false)\n }\n }}\n onKeyDown={handleKeyDown}\n />\n {typeof document !== 'undefined' &&\n createPortal(\n <AnimatePresence>\n {isOpen && (\n <motion.ul\n id={listboxId}\n ref={setFloating}\n role=\"listbox\"\n initial={reducedMotion ? false : { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={reducedMotion ? { opacity: 1 } : { opacity: 0 }}\n transition={reducedMotion ? { duration: 0 } : tweens.fade}\n style={floatingStyles}\n className=\"z-popover overflow-auto rounded-overlay bg-surface-overlay shadow-raised-hover\"\n >\n {isLoading ? (\n <li className=\"flex items-center gap-ds-03 px-ds-04 py-ds-03 text-body-md text-surface-fg-muted\">\n <Spinner size=\"sm\" />\n {loadingText}\n </li>\n ) : filtered.length === 0 ? (\n <li className=\"px-ds-04 py-ds-03 text-body-md text-surface-fg-muted\">{emptyText}</li>\n ) : (\n filtered.map((option, index) => (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events -- WAI-ARIA combobox: keyboard nav is on the input via aria-activedescendant; options are pointer affordances, not focusable tab stops\n <li\n key={option.value}\n id={`${optionIdPrefix}-${index}`}\n role=\"option\"\n aria-selected={highlightedIndex === index}\n title={option.label}\n className={cn(\n 'cursor-pointer truncate px-ds-04 py-ds-03 text-body-md text-surface-fg transition-colors duration-fast-01',\n highlightedIndex === index && 'bg-accent-3',\n selected?.value === option.value && 'font-semibold',\n )}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => handleSelect(option)}\n onMouseEnter={() => setHighlightedIndex(index)}\n >\n {renderOption ? renderOption(option, query) : <HighlightMatch label={option.label} query={query} />}\n </li>\n ))\n )}\n </motion.ul>\n )}\n </AnimatePresence>,\n document.body,\n )}\n </div>\n )\n },\n)\nAutocomplete.displayName = 'Autocomplete'\n\nexport { Autocomplete }\n"],"mappings":";;;;;;;;;;;;;AAmDA,SAAS,EAAe,EAAE,UAAO,YAA2C;CAC1E,IAAM,IAAM,IAAQ,EAAM,YAAY,CAAC,CAAC,QAAQ,EAAM,YAAY,CAAC,IAAI;CAEvE,OADI,MAAQ,KAAW,kBAAA,GAAA,EAAA,UAAG,EAAQ,CAAA,IAEhC,kBAAA,GAAA,EAAA,UAAA;EACG,EAAM,MAAM,GAAG,CAAG;EACnB,kBAAC,QAAD;GAAM,WAAU;aAAgC,EAAM,MAAM,GAAK,IAAM,EAAM,MAAM;EAAQ,CAAA;EAC1F,EAAM,MAAM,IAAM,EAAM,MAAM;CAC/B,EAAA,CAAA;AAEN;AAEA,IAAM,IAAe,EAAM,YAEvB,EACE,YACA,UACA,kBAAe,MACf,kBACA,gBACA,eAAY,cACZ,aACA,MAAA,GACA,UACA,eAAY,IACZ,iBAAc,YACd,iBACA,cACA,IAAI,GACJ,GAAG,KAEL,MACG;CACH,IAAM,KAAa,EAAM,MAAM,GACzB,IAAS,KAAc,IACvB,IAAY,GAAG,EAAO,WACtB,IAAiB,GAAG,EAAO,UAG3B,IAAe,MAAU,KAAA,GACzB,CAAC,GAAe,KAAoB,EAAM,SAAoC,CAAY,GAC1F,IAAW,IAAe,IAAQ,GAElC,CAAC,GAAO,KAAY,EAAM,SAAS,GAAU,SAAS,EAAE,GACxD,CAAC,GAAQ,KAAa,EAAM,SAAS,EAAK,GAC1C,CAAC,GAAkB,KAAuB,EAAM,SAAS,EAAE,GAC3D,IAAc,EAAM,OAAyB,IAAI,GACjD,IAAe,EAAM,OAAuB,IAAI,GAChD,IAAc,EAAM,OAAyB,IAAI,GACjD,EAAE,qBAAkB,EAAU,GAG9B,EAAE,SAAM,uBAAmB,EAAY;EAC3C,MAAM;EACN,WAAW;EACX,sBAAsB;EACtB,YAAY;GACV,EAAO,CAAC;GACR,EAAK;GACL,EAAM;GACN,EAAe,EACb,MAAM,EAAE,oBAAiB,UAAO,eAAY;IAC1C,OAAO,OAAO,EAAS,SAAS,OAAO;KACrC,WAAW,GAAG,KAAK,IAAI,GAAiB,GAAG,EAAE;KAC7C,OAAO,GAAG,EAAM,UAAU,MAAM;IAClC,CAAC;GACH,EACF,CAAC;EACH;CACF,CAAC,GAEK,KAAe,EAAM,aACxB,MAAgC;EAE/B,AADA,EAAa,UAAU,GACvB,EAAK,aAAa,CAAI;CACxB,GACA,CAAC,CAAI,CACP,GAEM,KAAmB,EAAM,aAC5B,MAAkC;EAEjC,AADA,EAAY,UAAU,GAClB,OAAO,KAAQ,aAAY,EAAI,CAAI,IAC9B,MAAK,EAAyD,UAAU;CACnF,GACA,CAAC,CAAG,CACN,GAEM,KAAc,EAAM,aACvB,MAAkC;EAEjC,AADA,EAAY,UAAU,GACtB,EAAK,YAAY,CAAI;CACvB,GACA,CAAC,CAAI,CACP;CAGA,EAAM,gBAAgB;EACpB,EAAS,GAAU,SAAS,EAAE;CAChC,GAAG,CAAC,CAAQ,CAAC;CAEb,IAAM,IAAW,EAAM,cAEnB,IACI,EAAQ,QAAQ,MAAM,EAAE,MAAM,YAAY,CAAC,CAAC,SAAS,EAAM,YAAY,CAAC,CAAC,IACzE,GACN,CAAC,GAAS,CAAK,CACjB,GAEM,IAAe,EAAM,aACxB,MAA+B;EAK9B,AAJA,EAAS,EAAO,KAAK,GACrB,EAAU,EAAK,GACf,EAAoB,EAAE,GACjB,KAAc,EAAiB,CAAM,GAC1C,IAAgB,CAAM;CACxB,GACA,CAAC,GAAc,CAAa,CAC9B,GAEM,KAAgB,EAAM,aACzB,MAA2B;EACtB,QACJ;OAAI,CAAC,GAAQ;IACX,CAAI,EAAE,QAAQ,eAAe,EAAE,QAAQ,YAAS,EAAU,EAAI;IAC9D;GACF;GACA,QAAQ,EAAE,KAAV;IACE,KAAK;KAEH,AADA,EAAE,eAAe,GACjB,GAAqB,MAAM,KAAK,IAAI,IAAI,GAAG,EAAS,SAAS,CAAC,CAAC;KAC/D;IACF,KAAK;KAEH,AADA,EAAE,eAAe,GACjB,GAAqB,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC,CAAC;KAC7C;IACF,KAAK;KAEH,AADA,EAAE,eAAe,GACjB,EAAoB,CAAC;KACrB;IACF,KAAK;KAEH,AADA,EAAE,eAAe,GACjB,EAAoB,EAAS,SAAS,CAAC;KACvC;IACF,KAAK;KAEH,AADA,EAAE,eAAe,GACb,KAAoB,KAAK,EAAS,MAAmB,EAAa,EAAS,EAAiB;KAChG;IACF,KAAK;KAEH,AADA,EAAU,EAAK,GACf,EAAoB,EAAE;KACtB;GACJ;EA1BA;CA2BF,GACA;EAAC;EAAU;EAAQ;EAAU;EAAkB;CAAY,CAC7D,GAIM,KAAW,EAAa,GACxB,KAAe,CAAC,EAAE,KAAc,GAAS,UACzC,KAAsB,KAAoB,IAAI,GAAG,EAAe,GAAG,MAAqB,KAAA;CAE9F,OACE,kBAAC,OAAD;EAAK,KAAK;EAAc,WAAW,EAAG,YAAY,CAAS;EAAG,GAAI;YAAlE,CACE,kBAAC,IAAD;GACE,KAAK;GACL,MAAK;GACL,MAAK;GACC,MAAA;GACC;GACP,IAAI;GACJ,OAAO;GACM;GACH;GACV,iBAAe;GACf,qBAAkB;GAClB,iBAAe,IAAS,IAAY,KAAA;GACpC,yBAAuB;GACvB,cAAY,KAAe,KAAA,IAAY;GACvC,YAAY,IAAY,kBAAC,GAAD,EAAS,MAAK,KAAM,CAAA,IAAI,KAAA;GAChD,WAAW,MAAM;IAGf,AAFA,EAAS,EAAE,OAAO,KAAK,GACvB,EAAU,EAAI,GACd,EAAoB,EAAE;GACxB;GACA,eAAe,EAAU,EAAI;GAC7B,SAAS,MAAM;IACb,IAAM,IAAS,EAAE;IACjB,AAAI,CAAC,EAAa,SAAS,SAAS,CAAM,KAAK,CAAC,EAAY,SAAS,SAAS,CAAM,KAClF,EAAU,EAAK;GAEnB;GACA,WAAW;EACZ,CAAA,GACA,OAAO,WAAa,OACnB,EACE,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,EAAO,IAAR;GACE,IAAI;GACJ,KAAK;GACL,MAAK;GACL,SAAS,MAAwB,EAAE,SAAS,EAAE;GAC9C,SAAS,EAAE,SAAS,EAAE;GACtB,MAAM,IAAgB,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;GACpD,YAAY,IAAgB,EAAE,UAAU,EAAE,IAAI,EAAO;GACrD,OAAO;GACP,WAAU;aAET,IACC,kBAAC,MAAD;IAAI,WAAU;cAAd,CACE,kBAAC,GAAD,EAAS,MAAK,KAAM,CAAA,GACnB,CACC;QACF,EAAS,WAAW,IACtB,kBAAC,MAAD;IAAI,WAAU;cAAwD;GAAc,CAAA,IAEpF,EAAS,KAAK,GAAQ,MAEpB,kBAAC,MAAD;IAEE,IAAI,GAAG,EAAe,GAAG;IACzB,MAAK;IACL,iBAAe,MAAqB;IACpC,OAAO,EAAO;IACd,WAAW,EACT,6GACA,MAAqB,KAAS,eAC9B,GAAU,UAAU,EAAO,SAAS,eACtC;IACA,cAAc,MAAM,EAAE,eAAe;IACrC,eAAe,EAAa,CAAM;IAClC,oBAAoB,EAAoB,CAAK;cAE5C,IAAe,EAAa,GAAQ,CAAK,IAAI,kBAAC,GAAD;KAAgB,OAAO,EAAO;KAAc;IAAQ,CAAA;GAChG,GAfG,EAAO,KAeV,CACL;EAEM,CAAA,EAEE,CAAA,GACjB,SAAS,IACX,CACC;;AAET,CACF;AACA,EAAa,cAAc"}
|
|
1
|
+
{"version":3,"file":"autocomplete.js","names":[],"sources":["../../src/ui/autocomplete.tsx"],"sourcesContent":["'use client'\n\nimport { autoUpdate, flip, offset, shift, size as sizeMiddleware, useFloating } from '@floating-ui/react-dom'\nimport { AnimatePresence, motion } from 'framer-motion'\nimport * as React from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { useMotion } from '../motion/motion-provider'\nimport { useFormField } from './form'\nimport { Input, type InputProps } from './input'\nimport { tweens } from './lib/motion'\nimport { cn } from './lib/utils'\nimport { Spinner } from './spinner'\n\nexport type AutocompleteOption = {\n label: string\n value: string\n}\n\n/**\n * A free-text input with a live-filtered dropdown, keyboard navigation, and\n * combobox ARIA. The field itself is the DS `Input`, so it inherits size,\n * error/state painting, read-only, hover, and FormField wiring.\n *\n * Free-text (no forced selection) — for enforced selection use `Combobox`.\n * `value`/`defaultValue` are a full `AutocompleteOption` (or null).\n */\nexport type AutocompleteProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> & {\n options: AutocompleteOption[]\n /** Controlled selection. */\n value?: AutocompleteOption | null\n /** Initial selection for uncontrolled mode. */\n defaultValue?: AutocompleteOption | null\n onValueChange?: (option: AutocompleteOption) => void\n placeholder?: string\n emptyText?: string\n disabled?: boolean\n /** Input size (forwarded to the composed `Input`). */\n size?: InputProps['size']\n /** Field state (forwarded to `Input`); overrides FormField auto-consumption. */\n state?: InputProps['state']\n /** Show a loading spinner + `loadingText` (async \"type to search\"). */\n isLoading?: boolean\n loadingText?: string\n /** Custom option renderer. Receives the option and the current query. */\n renderOption?: (option: AutocompleteOption, query: string) => React.ReactNode\n className?: string\n id?: string\n}\n\n/** Bold the matched substring inside an option label. */\nfunction HighlightMatch({ label, query }: { label: string; query: string }) {\n const idx = query ? label.toLowerCase().indexOf(query.toLowerCase()) : -1\n if (idx === -1) return <>{label}</>\n return (\n <>\n {label.slice(0, idx)}\n <span className=\"font-semibold text-accent-11\">{label.slice(idx, idx + query.length)}</span>\n {label.slice(idx + query.length)}\n </>\n )\n}\n\nconst Autocomplete = React.forwardRef<HTMLInputElement, AutocompleteProps>(\n (\n {\n options,\n value,\n defaultValue = null,\n onValueChange,\n placeholder,\n emptyText = 'No options',\n disabled,\n size,\n state,\n isLoading = false,\n loadingText = 'Loading…',\n renderOption,\n className,\n id: externalId,\n ...props\n },\n ref,\n ) => {\n const internalId = React.useId()\n const baseId = externalId || internalId\n const listboxId = `${baseId}-listbox`\n const optionIdPrefix = `${baseId}-option`\n\n // Controlled / uncontrolled selection\n const isControlled = value !== undefined\n const [internalValue, setInternalValue] = React.useState<AutocompleteOption | null>(defaultValue)\n const selected = isControlled ? value : internalValue\n\n const [query, setQuery] = React.useState(selected?.label ?? '')\n const [isOpen, setIsOpen] = React.useState(false)\n const [highlightedIndex, setHighlightedIndex] = React.useState(-1)\n const internalRef = React.useRef<HTMLInputElement>(null)\n const containerRef = React.useRef<HTMLDivElement>(null)\n const floatingRef = React.useRef<HTMLUListElement>(null)\n const { reducedMotion } = useMotion()\n\n // Floating UI — anchor the dropdown to the whole field (container width)\n const { refs, floatingStyles } = useFloating({\n open: isOpen,\n placement: 'bottom-start',\n whileElementsMounted: autoUpdate,\n middleware: [\n offset(4),\n flip(),\n shift(),\n sizeMiddleware({\n apply({ availableHeight, rects, elements }) {\n Object.assign(elements.floating.style, {\n maxHeight: `${Math.min(availableHeight, 240)}px`,\n width: `${rects.reference.width}px`,\n })\n },\n }),\n ],\n })\n\n const setContainer = React.useCallback(\n (node: HTMLDivElement | null) => {\n containerRef.current = node\n refs.setReference(node)\n },\n [refs],\n )\n\n const composedInputRef = React.useCallback(\n (node: HTMLInputElement | null) => {\n internalRef.current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLInputElement | null>).current = node\n },\n [ref],\n )\n\n const setFloating = React.useCallback(\n (node: HTMLUListElement | null) => {\n floatingRef.current = node\n refs.setFloating(node)\n },\n [refs],\n )\n\n // Sync query when the selection changes externally\n React.useEffect(() => {\n setQuery(selected?.label ?? '')\n }, [selected])\n\n const filtered = React.useMemo(\n () =>\n query\n ? options.filter((o) => o.label.toLowerCase().includes(query.toLowerCase()))\n : options,\n [options, query],\n )\n\n const handleSelect = React.useCallback(\n (option: AutocompleteOption) => {\n setQuery(option.label)\n setIsOpen(false)\n setHighlightedIndex(-1)\n if (!isControlled) setInternalValue(option)\n onValueChange?.(option)\n },\n [isControlled, onValueChange],\n )\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent) => {\n if (disabled) return\n if (!isOpen) {\n if (e.key === 'ArrowDown' || e.key === 'Enter') setIsOpen(true)\n return\n }\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n setHighlightedIndex((i) => Math.min(i + 1, filtered.length - 1))\n break\n case 'ArrowUp':\n e.preventDefault()\n setHighlightedIndex((i) => Math.max(i - 1, 0))\n break\n case 'Home':\n e.preventDefault()\n setHighlightedIndex(0)\n break\n case 'End':\n e.preventDefault()\n setHighlightedIndex(filtered.length - 1)\n break\n case 'Enter':\n e.preventDefault()\n if (highlightedIndex >= 0 && filtered[highlightedIndex]) handleSelect(filtered[highlightedIndex])\n break\n case 'Escape':\n setIsOpen(false)\n setHighlightedIndex(-1)\n break\n }\n },\n [disabled, isOpen, filtered, highlightedIndex, handleSelect],\n )\n\n // FormField wiring is auto-consumed by Input; only used here to decide the\n // standalone accessible-name fallback + the combobox aria-controls id.\n const fieldCtx = useFormField()\n const hasFieldName = !!(externalId || fieldCtx.inputId)\n const highlightedOptionId = highlightedIndex >= 0 ? `${optionIdPrefix}-${highlightedIndex}` : undefined\n\n return (\n <div ref={setContainer} className={cn('relative', className)} {...props}>\n <Input\n ref={composedInputRef}\n type=\"text\"\n role=\"combobox\"\n size={size}\n state={state}\n id={externalId}\n value={query}\n placeholder={placeholder}\n disabled={disabled}\n aria-expanded={isOpen}\n aria-autocomplete=\"list\"\n aria-controls={isOpen ? listboxId : undefined}\n aria-activedescendant={highlightedOptionId}\n aria-label={hasFieldName ? undefined : placeholder}\n endSection={isLoading ? <Spinner size=\"sm\" /> : undefined}\n onChange={(e) => {\n setQuery(e.target.value)\n setIsOpen(true)\n setHighlightedIndex(-1)\n }}\n onFocus={() => setIsOpen(true)}\n onBlur={(e) => {\n const target = e.relatedTarget as Node | null\n if (!containerRef.current?.contains(target) && !floatingRef.current?.contains(target)) {\n setIsOpen(false)\n }\n }}\n onKeyDown={handleKeyDown}\n />\n {typeof document !== 'undefined' &&\n createPortal(\n <AnimatePresence>\n {isOpen && (\n <motion.ul\n id={listboxId}\n ref={setFloating}\n role=\"listbox\"\n initial={reducedMotion ? false : { opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={reducedMotion ? { opacity: 1 } : { opacity: 0 }}\n transition={reducedMotion ? { duration: 0 } : tweens.fade}\n style={floatingStyles}\n className=\"z-popover overflow-auto rounded-overlay bg-surface-overlay shadow-raised-hover\"\n >\n {isLoading ? (\n <li className=\"flex items-center gap-ds-03 px-ds-04 py-ds-03 text-body-md text-surface-fg-muted\">\n <Spinner size=\"sm\" />\n {loadingText}\n </li>\n ) : filtered.length === 0 ? (\n <li className=\"px-ds-04 py-ds-03 text-body-md text-surface-fg-muted\">{emptyText}</li>\n ) : (\n filtered.map((option, index) => (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events -- WAI-ARIA combobox: keyboard nav is on the input via aria-activedescendant; options are pointer affordances, not focusable tab stops\n <li\n key={option.value}\n id={`${optionIdPrefix}-${index}`}\n role=\"option\"\n aria-selected={highlightedIndex === index}\n title={option.label}\n className={cn(\n 'cursor-pointer truncate px-ds-04 py-ds-03 text-body-md text-surface-fg transition-colors duration-fast-01',\n highlightedIndex === index && 'bg-accent-4',\n selected?.value === option.value && 'font-semibold',\n )}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => handleSelect(option)}\n onMouseEnter={() => setHighlightedIndex(index)}\n >\n {renderOption ? renderOption(option, query) : <HighlightMatch label={option.label} query={query} />}\n </li>\n ))\n )}\n </motion.ul>\n )}\n </AnimatePresence>,\n document.body,\n )}\n </div>\n )\n },\n)\nAutocomplete.displayName = 'Autocomplete'\n\nexport { Autocomplete }\n"],"mappings":"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"}
|
package/dist/ui/avatar.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../../src/ui/avatar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,eAAe,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"avatar.d.ts","sourceRoot":"","sources":["../../src/ui/avatar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,eAAe,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAc9B,eAAO,MAAM,cAAc;;;8EAmB1B,CAAA;AAED,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAA;AAEjE,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;AA2E7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,WAAW,WACf,SAAQ,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,EACnF,YAAY,CAAC,OAAO,cAAc,CAAC;IACrC,8EAA8E;IAC9E,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,gCAAgC;IAChC,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC,SAAS,CAAA;IACxC,+CAA+C;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC3B;AAED,QAAA,MAAM,MAAM,qFA8EV,CAAA;AAGF,QAAA,MAAM,WAAW,gKAkBf,CAAA;AAGF,MAAM,WAAW,mBACf,SAAQ,KAAK,CAAC,wBAAwB,CAAC,OAAO,eAAe,CAAC,QAAQ,CAAC;IACvE;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,QAAA,MAAM,cAAc,6FAmClB,CAAA;AAGF,OAAO,EAAE,MAAM,EAAE,cAAc,EAAC,WAAW,EAAE,CAAA"}
|
package/dist/ui/avatar.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { springs as e } from "./lib/motion.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
3
|
+
import { MotionPreference as t } from "../_chunks/motion-preference.js";
|
|
4
|
+
import { cn as n } from "./lib/utils.js";
|
|
5
|
+
import { Fallback as r, Image as i, Root as a } from "../_chunks/primitives/react-avatar.js";
|
|
6
|
+
import { Dot as o } from "./dot.js";
|
|
7
|
+
import { Skeleton as s } from "./skeleton.js";
|
|
8
|
+
import * as c from "react";
|
|
9
|
+
import { jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
10
|
+
import { motion as d } from "framer-motion";
|
|
11
|
+
import { cva as f } from "class-variance-authority";
|
|
11
12
|
//#region src/ui/avatar.tsx
|
|
12
|
-
var
|
|
13
|
+
var p = c.createContext("circle"), m = c.createContext("md"), h = f("relative flex shrink-0 overflow-hidden", {
|
|
13
14
|
variants: {
|
|
14
15
|
size: {
|
|
15
16
|
xs: "h-ds-xs w-ds-xs",
|
|
@@ -28,37 +29,37 @@ var f = s.createContext("circle"), p = s.createContext("md"), m = d("relative fl
|
|
|
28
29
|
size: "md",
|
|
29
30
|
shape: "circle"
|
|
30
31
|
}
|
|
31
|
-
}),
|
|
32
|
+
}), g = {
|
|
32
33
|
online: "success",
|
|
33
34
|
offline: "neutral",
|
|
34
35
|
busy: "error",
|
|
35
36
|
away: "warning"
|
|
36
|
-
},
|
|
37
|
+
}, _ = {
|
|
37
38
|
online: "Online",
|
|
38
39
|
offline: "Offline",
|
|
39
40
|
busy: "Busy",
|
|
40
41
|
away: "Away"
|
|
41
|
-
},
|
|
42
|
+
}, v = {
|
|
42
43
|
xs: "xs",
|
|
43
44
|
sm: "sm",
|
|
44
45
|
md: "md",
|
|
45
46
|
lg: "lg",
|
|
46
47
|
xl: "lg"
|
|
47
|
-
},
|
|
48
|
+
}, y = {
|
|
48
49
|
lead: "ring-accent-7",
|
|
49
50
|
admin: "ring-warning-7",
|
|
50
51
|
client: "ring-info-7"
|
|
51
|
-
},
|
|
52
|
+
}, b = {
|
|
52
53
|
circle: "rounded-pill",
|
|
53
54
|
square: "rounded-none",
|
|
54
55
|
rounded: "rounded-control"
|
|
55
|
-
},
|
|
56
|
+
}, x = {
|
|
56
57
|
xs: "text-body-xs",
|
|
57
58
|
sm: "text-body-xs",
|
|
58
59
|
md: "text-body-sm",
|
|
59
60
|
lg: "text-body-md",
|
|
60
61
|
xl: "text-heading-xs"
|
|
61
|
-
},
|
|
62
|
+
}, S = [
|
|
62
63
|
{
|
|
63
64
|
bg: "bg-accent-3",
|
|
64
65
|
text: "text-accent-11"
|
|
@@ -92,77 +93,77 @@ var f = s.createContext("circle"), p = s.createContext("md"), m = d("relative fl
|
|
|
92
93
|
text: "text-category-cyan-11"
|
|
93
94
|
}
|
|
94
95
|
];
|
|
95
|
-
function
|
|
96
|
+
function C(e) {
|
|
96
97
|
let t = 5381;
|
|
97
98
|
for (let n = 0; n < e.length; n++) t = (t << 5) + t + e.charCodeAt(n) | 0;
|
|
98
|
-
return
|
|
99
|
+
return S[Math.abs(t) % S.length];
|
|
99
100
|
}
|
|
100
|
-
var
|
|
101
|
-
let
|
|
102
|
-
if (
|
|
103
|
-
ref:
|
|
104
|
-
className:
|
|
105
|
-
children: /* @__PURE__ */
|
|
106
|
-
className:
|
|
107
|
-
size:
|
|
108
|
-
shape:
|
|
101
|
+
var w = c.forwardRef(({ className: r, size: i, shape: c, status: f, ring: x, badge: S, loading: C, children: w, ...T }, E) => {
|
|
102
|
+
let D = c ?? "circle", O = x && x !== "none" ? n("ring-2 ring-offset-2 ring-offset-surface-panel", y[x], b[D]) : void 0;
|
|
103
|
+
if (C) return /* @__PURE__ */ l("span", {
|
|
104
|
+
ref: E,
|
|
105
|
+
className: n("relative inline-flex shrink-0", O),
|
|
106
|
+
children: /* @__PURE__ */ l(s, {
|
|
107
|
+
className: n(h({
|
|
108
|
+
size: i,
|
|
109
|
+
shape: c
|
|
109
110
|
})),
|
|
110
111
|
"data-slot": "avatar-skeleton"
|
|
111
112
|
})
|
|
112
113
|
});
|
|
113
|
-
let
|
|
114
|
-
return /* @__PURE__ */
|
|
115
|
-
value:
|
|
116
|
-
children: /* @__PURE__ */
|
|
117
|
-
value:
|
|
118
|
-
children: /* @__PURE__ */
|
|
119
|
-
className:
|
|
114
|
+
let k = S !== void 0 && S !== 0;
|
|
115
|
+
return /* @__PURE__ */ l(t, { children: /* @__PURE__ */ l(p.Provider, {
|
|
116
|
+
value: D,
|
|
117
|
+
children: /* @__PURE__ */ l(m.Provider, {
|
|
118
|
+
value: i ?? "md",
|
|
119
|
+
children: /* @__PURE__ */ u("span", {
|
|
120
|
+
className: n("relative inline-flex shrink-0", O),
|
|
120
121
|
children: [
|
|
121
|
-
/* @__PURE__ */
|
|
122
|
-
ref:
|
|
123
|
-
className:
|
|
124
|
-
size:
|
|
125
|
-
shape:
|
|
126
|
-
}),
|
|
127
|
-
...
|
|
128
|
-
children:
|
|
122
|
+
/* @__PURE__ */ l(a, {
|
|
123
|
+
ref: E,
|
|
124
|
+
className: n(h({
|
|
125
|
+
size: i,
|
|
126
|
+
shape: c
|
|
127
|
+
}), r),
|
|
128
|
+
...T,
|
|
129
|
+
children: w
|
|
129
130
|
}),
|
|
130
|
-
|
|
131
|
+
f && /* @__PURE__ */ l("span", {
|
|
131
132
|
className: "absolute bottom-0 right-0",
|
|
132
133
|
role: "img",
|
|
133
|
-
"aria-label":
|
|
134
|
-
children: /* @__PURE__ */
|
|
135
|
-
color:
|
|
136
|
-
size:
|
|
134
|
+
"aria-label": _[f],
|
|
135
|
+
children: /* @__PURE__ */ l(o, {
|
|
136
|
+
color: g[f],
|
|
137
|
+
size: v[i ?? "md"],
|
|
137
138
|
withBorder: !0,
|
|
138
139
|
"aria-hidden": !0
|
|
139
140
|
})
|
|
140
141
|
}),
|
|
141
|
-
|
|
142
|
-
className: "absolute -right-0.5 -top-0.5 h-ds-03 w-ds-03 rounded-pill bg-error-9 ring-2 ring-surface-
|
|
142
|
+
k && (S === "dot" ? /* @__PURE__ */ l("span", {
|
|
143
|
+
className: "absolute -right-0.5 -top-0.5 h-ds-03 w-ds-03 rounded-pill bg-error-9 ring-2 ring-surface-panel",
|
|
143
144
|
"data-slot": "avatar-badge-dot",
|
|
144
145
|
"aria-hidden": "true"
|
|
145
|
-
}) : typeof
|
|
146
|
+
}) : typeof S == "number" ? /* @__PURE__ */ l(d.span, {
|
|
146
147
|
initial: { scale: 0 },
|
|
147
148
|
animate: { scale: 1 },
|
|
148
149
|
transition: e.smooth,
|
|
149
|
-
className: "absolute -right-1 -top-1 flex min-w-ds-05 items-center justify-center rounded-pill bg-error-9 px-1 text-[10px] font-bold leading-[16px] text-error-fg ring-2 ring-surface-
|
|
150
|
+
className: "absolute -right-1 -top-1 flex min-w-ds-05 items-center justify-center rounded-pill bg-error-9 px-1 text-[10px] font-bold leading-[16px] text-error-fg ring-2 ring-surface-panel",
|
|
150
151
|
"data-slot": "avatar-badge",
|
|
151
152
|
role: "status",
|
|
152
|
-
"aria-label": `${
|
|
153
|
-
children:
|
|
154
|
-
}) : /* @__PURE__ */
|
|
153
|
+
"aria-label": `${S > 99 ? "99+" : S} notifications`,
|
|
154
|
+
children: S > 99 ? "99+" : S
|
|
155
|
+
}) : /* @__PURE__ */ l("span", {
|
|
155
156
|
className: "absolute -right-1 -top-1",
|
|
156
157
|
"data-slot": "avatar-badge-custom",
|
|
157
|
-
children:
|
|
158
|
+
children: S
|
|
158
159
|
}))
|
|
159
160
|
]
|
|
160
161
|
})
|
|
161
162
|
})
|
|
162
|
-
});
|
|
163
|
+
}) });
|
|
163
164
|
});
|
|
164
|
-
|
|
165
|
-
var
|
|
165
|
+
w.displayName = a.displayName;
|
|
166
|
+
var T = c.forwardRef(({ className: r, ...a }, o) => /* @__PURE__ */ l(t, { children: /* @__PURE__ */ l(d.span, {
|
|
166
167
|
initial: { scale: .96 },
|
|
167
168
|
animate: {
|
|
168
169
|
opacity: 1,
|
|
@@ -170,23 +171,23 @@ var w = s.forwardRef(({ className: n, ...i }, a) => /* @__PURE__ */ c(u.span, {
|
|
|
170
171
|
},
|
|
171
172
|
transition: e.smooth,
|
|
172
173
|
className: "absolute inset-0 h-full w-full",
|
|
173
|
-
children: /* @__PURE__ */
|
|
174
|
-
ref:
|
|
175
|
-
className:
|
|
176
|
-
...
|
|
174
|
+
children: /* @__PURE__ */ l(i, {
|
|
175
|
+
ref: o,
|
|
176
|
+
className: n("aspect-square h-full w-full", r),
|
|
177
|
+
...a
|
|
177
178
|
})
|
|
178
|
-
}));
|
|
179
|
-
|
|
180
|
-
var
|
|
181
|
-
let
|
|
182
|
-
return /* @__PURE__ */
|
|
179
|
+
}) }));
|
|
180
|
+
T.displayName = i.displayName;
|
|
181
|
+
var E = c.forwardRef(({ className: e, colorSeed: t, children: i, ...a }, o) => {
|
|
182
|
+
let s = typeof i == "string" ? i : "", u = C(t ?? s), d = c.useContext(p), f = c.useContext(m), h = d === "square" ? "rounded-none" : d === "rounded" ? "rounded-control" : "rounded-pill", g = s.length === 1 ? "tracking-wide" : "tracking-normal";
|
|
183
|
+
return /* @__PURE__ */ l(r, {
|
|
183
184
|
ref: o,
|
|
184
185
|
"data-slot": "avatar-fallback",
|
|
185
|
-
className:
|
|
186
|
+
className: n("flex h-full w-full items-center justify-center font-semibold", h, x[f], u.bg, u.text, g, e),
|
|
186
187
|
...a,
|
|
187
188
|
children: i
|
|
188
189
|
});
|
|
189
190
|
});
|
|
190
|
-
|
|
191
|
+
E.displayName = r.displayName;
|
|
191
192
|
//#endregion
|
|
192
|
-
export {
|
|
193
|
+
export { w as Avatar, E as AvatarFallback, T as AvatarImage, h as avatarVariants };
|
package/dist/ui/avatar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"avatar.js","names":[],"sources":["../../src/ui/avatar.tsx"],"sourcesContent":["'use client'\n\nimport * as AvatarPrimitive from \"@primitives/react-avatar\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { motion } from \"framer-motion\"\nimport * as React from \"react\"\n\nimport { Dot, type DotColor, type DotSize } from \"./dot\"\nimport { springs } from \"./lib/motion\"\nimport { cn } from \"./lib/utils\"\nimport { Skeleton } from \"./skeleton\"\n\n// ── Contexts so AvatarFallback can inherit shape & size from Avatar ──\ntype AvatarShape = 'circle' | 'square' | 'rounded'\ntype AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'\nconst AvatarShapeContext = React.createContext<AvatarShape>('circle')\nconst AvatarSizeContext = React.createContext<AvatarSize>('md')\n\nexport const avatarVariants = cva(\n 'relative flex shrink-0 overflow-hidden',\n {\n variants: {\n size: {\n xs: 'h-ds-xs w-ds-xs',\n sm: 'h-ds-sm w-ds-sm',\n md: 'h-ds-md w-ds-md',\n lg: 'h-ds-lg w-ds-lg',\n xl: 'h-ds-xl w-ds-xl',\n },\n shape: {\n circle: 'rounded-pill',\n square: 'rounded-none',\n rounded: 'rounded-control',\n },\n },\n defaultVariants: { size: 'md', shape: 'circle' },\n }\n)\n\nexport type AvatarStatus = 'online' | 'offline' | 'busy' | 'away'\n\nexport type AvatarRing = 'none' | 'lead' | 'admin' | 'client'\n\n// Presence status → shared Dot intent colour.\nconst statusDotColor: Record<AvatarStatus, DotColor> = {\n online: 'success',\n offline: 'neutral',\n busy: 'error',\n away: 'warning',\n}\n\nconst statusLabelMap: Record<AvatarStatus, string> = {\n online: 'Online',\n offline: 'Offline',\n busy: 'Busy',\n away: 'Away',\n}\n\n/** Avatar size → Dot size (the status dot scales with the avatar). */\nconst statusDotSize: Record<AvatarSize, DotSize> = {\n xs: 'xs',\n sm: 'sm',\n md: 'md',\n lg: 'lg',\n xl: 'lg',\n}\n\n// ── Role ring ───────────────────────────────────────────────────────────────\n\nconst ringColorMap: Record<Exclude<AvatarRing, 'none'>, string> = {\n lead: 'ring-accent-7',\n admin: 'ring-warning-7',\n client: 'ring-info-7',\n}\n\nconst ringShapeMap: Record<string, string> = {\n circle: 'rounded-pill',\n square: 'rounded-none',\n rounded: 'rounded-control',\n}\n\n// ── Fallback font sizes that scale with avatar size ─────────────────────────\nconst fallbackTextSizeMap: Record<AvatarSize, string> = {\n xs: 'text-body-xs',\n sm: 'text-body-xs',\n md: 'text-body-sm',\n lg: 'text-body-md',\n xl: 'text-heading-xs',\n}\n\n// ── Deterministic fallback colors ───────────────────────────────────────────\n\nconst FALLBACK_COLORS = [\n { bg: 'bg-accent-3', text: 'text-accent-11' },\n { bg: 'bg-success-3', text: 'text-success-11' },\n { bg: 'bg-warning-3', text: 'text-warning-11' },\n { bg: 'bg-error-3', text: 'text-error-11' },\n { bg: 'bg-info-3', text: 'text-info-11' },\n { bg: 'bg-category-teal-3', text: 'text-category-teal-11' },\n { bg: 'bg-category-indigo-3', text: 'text-category-indigo-11' },\n { bg: 'bg-category-cyan-3', text: 'text-category-cyan-11' },\n] as const\n\n/**\n * Simple string hash that produces a deterministic index into FALLBACK_COLORS.\n * Uses djb2 for a reasonable distribution with short strings.\n */\nfunction getFallbackColor(seed: string): (typeof FALLBACK_COLORS)[number] {\n let hash = 5381\n for (let i = 0; i < seed.length; i++) {\n hash = ((hash << 5) + hash + seed.charCodeAt(i)) | 0\n }\n const index = Math.abs(hash) % FALLBACK_COLORS.length\n return FALLBACK_COLORS[index]\n}\n\n/**\n * Props for Avatar — a user/entity image container with size, shape, and presence-status variants.\n *\n * **Sizes:** `xs` | `sm` | `md` (default) | `lg` | `xl` — the status dot scales with the avatar size.\n *\n * **Shapes:** `circle` (default, round) | `square` (sharp corners) | `rounded` (rounded corners, for bots/apps)\n *\n * **Status dot:** `status=\"online\"` (green) | `\"offline\"` (muted) | `\"busy\"` (red) | `\"away\"` (amber).\n * The dot renders with `role=\"img\"` and an accessible `aria-label` — it is not purely decorative.\n *\n * **Role ring:** `ring=\"lead\"` (accent) | `\"admin\"` (warning) | `\"client\"` (info) — a colored ring\n * around the avatar indicating the user's role.\n *\n * **Badge:** `badge={5}` (number) | `badge=\"dot\"` (notification dot) | `badge={<Icon />}` (custom).\n * Numbers > 99 display as \"99+\". Badge is hidden when `0` or `undefined`.\n *\n * **Loading:** `loading={true}` shows a pulse skeleton placeholder.\n *\n * **Children:** Use `<AvatarImage>` for the photo and `<AvatarFallback>` for initials when the image fails.\n *\n * @example\n * // User avatar with photo and fallback initials:\n * <Avatar size=\"md\">\n * <AvatarImage src={user.avatarUrl} alt={user.name} />\n * <AvatarFallback>JD</AvatarFallback>\n * </Avatar>\n *\n * @example\n * // Online presence indicator in a team roster:\n * <Avatar size=\"lg\" status=\"online\">\n * <AvatarImage src={user.photoUrl} alt={user.name} />\n * <AvatarFallback>{user.initials}</AvatarFallback>\n * </Avatar>\n *\n * @example\n * // Square shape for a bot/integration logo:\n * <Avatar shape=\"square\" size=\"xl\">\n * <AvatarImage src=\"/logos/github.png\" alt=\"GitHub\" />\n * </Avatar>\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface AvatarProps\n extends Omit<React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>, 'children'>,\n VariantProps<typeof avatarVariants> {\n /** Optional status indicator displayed as a dot at the bottom-right corner */\n status?: AvatarStatus\n /** Role ring color indicator */\n ring?: AvatarRing\n /** Badge overlay: number, 'dot', or custom ReactNode */\n badge?: number | 'dot' | React.ReactNode\n /** Show loading skeleton instead of content */\n loading?: boolean\n children?: React.ReactNode\n}\n\nconst Avatar = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Root>,\n AvatarProps\n>(({ className, size, shape, status, ring, badge, loading, children, ...props }, ref) => {\n const resolvedShape = shape ?? 'circle'\n\n // Build ring classes for the outer wrapper\n const ringClasses = ring && ring !== 'none'\n ? cn('ring-2 ring-offset-2 ring-offset-surface-raised', ringColorMap[ring], ringShapeMap[resolvedShape])\n : undefined\n\n // Loading skeleton — early return\n if (loading) {\n return (\n <span ref={ref} className={cn('relative inline-flex shrink-0', ringClasses)}>\n <Skeleton\n className={cn(avatarVariants({ size, shape }))}\n data-slot=\"avatar-skeleton\"\n />\n </span>\n )\n }\n\n // Determine whether to render badge\n const showBadge = badge !== undefined && badge !== 0\n\n return (\n <AvatarShapeContext.Provider value={resolvedShape}>\n <AvatarSizeContext.Provider value={size ?? 'md'}>\n <span className={cn('relative inline-flex shrink-0', ringClasses)}>\n <AvatarPrimitive.Root\n ref={ref}\n className={cn(avatarVariants({ size, shape }), className)}\n {...props}\n >\n {children}\n </AvatarPrimitive.Root>\n {status && (\n <span\n className=\"absolute bottom-0 right-0\"\n role=\"img\"\n aria-label={statusLabelMap[status]}\n >\n {/* Shared Dot primitive: colour + contrast ring; wrapper owns position + a11y. */}\n <Dot color={statusDotColor[status]} size={statusDotSize[size ?? 'md']} withBorder aria-hidden />\n </span>\n )}\n {showBadge && (\n badge === 'dot' ? (\n <span\n className=\"absolute -right-0.5 -top-0.5 h-ds-03 w-ds-03 rounded-pill bg-error-9 ring-2 ring-surface-raised\"\n data-slot=\"avatar-badge-dot\"\n aria-hidden=\"true\"\n />\n ) : typeof badge === 'number' ? (\n <motion.span\n initial={{ scale: 0 }}\n animate={{ scale: 1 }}\n transition={springs.smooth}\n className=\"absolute -right-1 -top-1 flex min-w-ds-05 items-center justify-center rounded-pill bg-error-9 px-1 text-[10px] font-bold leading-[16px] text-error-fg ring-2 ring-surface-raised\"\n data-slot=\"avatar-badge\"\n role=\"status\"\n aria-label={`${badge > 99 ? '99+' : badge} notifications`}\n >\n {badge > 99 ? '99+' : badge}\n </motion.span>\n ) : (\n <span className=\"absolute -right-1 -top-1\" data-slot=\"avatar-badge-custom\">\n {badge}\n </span>\n )\n )}\n </span>\n </AvatarSizeContext.Provider>\n </AvatarShapeContext.Provider>\n )\n})\nAvatar.displayName = AvatarPrimitive.Root.displayName\n\nconst AvatarImage = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Image>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>\n>(({ className, ...props }, ref) => (\n <motion.span\n initial={{ scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springs.smooth}\n className=\"absolute inset-0 h-full w-full\"\n >\n <AvatarPrimitive.Image\n ref={ref}\n className={cn(\"aspect-square h-full w-full\", className)}\n {...props}\n />\n </motion.span>\n))\nAvatarImage.displayName = AvatarPrimitive.Image.displayName\n\nexport interface AvatarFallbackProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback> {\n /**\n * Seed string for deterministic color selection.\n * Falls back to the text content of `children` if not provided.\n */\n colorSeed?: string\n}\n\nconst AvatarFallback = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Fallback>,\n AvatarFallbackProps\n>(({ className, colorSeed, children, ...props }, ref) => {\n // Derive seed: explicit colorSeed > children text content > empty string\n const childrenText = typeof children === 'string' ? children : ''\n const seed = colorSeed ?? childrenText\n const color = getFallbackColor(seed)\n\n // Inherit shape and size from parent Avatar via context\n const shape = React.useContext(AvatarShapeContext)\n const size = React.useContext(AvatarSizeContext)\n const shapeClass = shape === 'square' ? 'rounded-none' : shape === 'rounded' ? 'rounded-control' : 'rounded-pill'\n\n // Letter-spacing based on character count\n const tracking = childrenText.length === 1 ? 'tracking-wide' : 'tracking-normal'\n\n return (\n <AvatarPrimitive.Fallback\n ref={ref}\n data-slot=\"avatar-fallback\"\n className={cn(\n 'flex h-full w-full items-center justify-center font-semibold',\n shapeClass,\n fallbackTextSizeMap[size],\n color.bg,\n color.text,\n tracking,\n className,\n )}\n {...props}\n >\n {children}\n </AvatarPrimitive.Fallback>\n )\n})\nAvatarFallback.displayName = AvatarPrimitive.Fallback.displayName\n\nexport { Avatar, AvatarFallback,AvatarImage }\n"],"mappings":";;;;;;;;;;;AAeA,IAAM,IAAqB,EAAM,cAA2B,QAAQ,GAC9D,IAAoB,EAAM,cAA0B,IAAI,GAEjD,IAAiB,EAC5B,0CACA;CACE,UAAU;EACR,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EACA,OAAO;GACL,QAAQ;GACR,QAAQ;GACR,SAAS;EACX;CACF;CACA,iBAAiB;EAAE,MAAM;EAAM,OAAO;CAAS;AACjD,CACF,GAOM,IAAiD;CACrD,QAAQ;CACR,SAAS;CACT,MAAM;CACN,MAAM;AACR,GAEM,IAA+C;CACnD,QAAQ;CACR,SAAS;CACT,MAAM;CACN,MAAM;AACR,GAGM,IAA6C;CACjD,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAIM,IAA4D;CAChE,MAAM;CACN,OAAO;CACP,QAAQ;AACV,GAEM,IAAuC;CAC3C,QAAQ;CACR,QAAQ;CACR,SAAS;AACX,GAGM,IAAkD;CACtD,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAIM,IAAkB;CACtB;EAAE,IAAI;EAAe,MAAM;CAAiB;CAC5C;EAAE,IAAI;EAAgB,MAAM;CAAkB;CAC9C;EAAE,IAAI;EAAgB,MAAM;CAAkB;CAC9C;EAAE,IAAI;EAAc,MAAM;CAAgB;CAC1C;EAAE,IAAI;EAAa,MAAM;CAAe;CACxC;EAAE,IAAI;EAAsB,MAAM;CAAwB;CAC1D;EAAE,IAAI;EAAwB,MAAM;CAA0B;CAC9D;EAAE,IAAI;EAAsB,MAAM;CAAwB;AAC5D;AAMA,SAAS,EAAiB,GAAgD;CACxE,IAAI,IAAO;CACX,KAAK,IAAI,IAAI,GAAG,IAAI,EAAK,QAAQ,KAC/B,KAAS,KAAQ,KAAK,IAAO,EAAK,WAAW,CAAC,IAAK;CAGrD,OAAO,EADO,KAAK,IAAI,CAAI,IAAI,EAAgB;AAEjD;AAyDA,IAAM,IAAS,EAAM,YAGlB,EAAE,cAAW,SAAM,UAAO,WAAQ,SAAM,UAAO,YAAS,aAAU,GAAG,KAAS,MAAQ;CACvF,IAAM,IAAgB,KAAS,UAGzB,IAAc,KAAQ,MAAS,SACjC,EAAG,mDAAmD,EAAa,IAAO,EAAa,EAAc,IACrG,KAAA;CAGJ,IAAI,GACF,OACE,kBAAC,QAAD;EAAW;EAAK,WAAW,EAAG,iCAAiC,CAAW;YACxE,kBAAC,GAAD;GACE,WAAW,EAAG,EAAe;IAAE;IAAM;GAAM,CAAC,CAAC;GAC7C,aAAU;EACX,CAAA;CACG,CAAA;CAKV,IAAM,IAAY,MAAU,KAAA,KAAa,MAAU;CAEnD,OACE,kBAAC,EAAmB,UAApB;EAA6B,OAAO;YACpC,kBAAC,EAAkB,UAAnB;GAA4B,OAAO,KAAQ;aAC3C,kBAAC,QAAD;IAAM,WAAW,EAAG,iCAAiC,CAAW;cAAhE;KACE,kBAAC,GAAD;MACO;MACL,WAAW,EAAG,EAAe;OAAE;OAAM;MAAM,CAAC,GAAG,CAAS;MACxD,GAAI;MAEH;KACmB,CAAA;KACrB,KACC,kBAAC,QAAD;MACE,WAAU;MACV,MAAK;MACL,cAAY,EAAe;gBAG3B,kBAAC,GAAD;OAAK,OAAO,EAAe;OAAS,MAAM,EAAc,KAAQ;OAAO,YAAA;OAAW,eAAA;MAAa,CAAA;KAC3F,CAAA;KAEP,MACC,MAAU,QACR,kBAAC,QAAD;MACE,WAAU;MACV,aAAU;MACV,eAAY;KACb,CAAA,IACC,OAAO,KAAU,WACnB,kBAAC,EAAO,MAAR;MACE,SAAS,EAAE,OAAO,EAAE;MACpB,SAAS,EAAE,OAAO,EAAE;MACpB,YAAY,EAAQ;MACpB,WAAU;MACV,aAAU;MACV,MAAK;MACL,cAAY,GAAG,IAAQ,KAAK,QAAQ,EAAM;gBAEzC,IAAQ,KAAK,QAAQ;KACX,CAAA,IAEb,kBAAC,QAAD;MAAM,WAAU;MAA2B,aAAU;gBAClD;KACG,CAAA;IAGN;;EACsB,CAAA;CACC,CAAA;AAEjC,CAAC;AACD,EAAO,cAAA,EAAmC;AAE1C,IAAM,IAAc,EAAM,YAGvB,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAO,MAAR;CACE,SAAS,EAAE,OAAO,IAAK;CACvB,SAAS;EAAE,SAAS;EAAG,OAAO;CAAE;CAChC,YAAY,EAAQ;CACpB,WAAU;WAEV,kBAAC,GAAD;EACO;EACL,WAAW,EAAG,+BAA+B,CAAS;EACtD,GAAI;CACL,CAAA;AACU,CAAA,CACd;AACD,EAAY,cAAA,EAAoC;AAWhD,IAAM,IAAiB,EAAM,YAG1B,EAAE,cAAW,cAAW,aAAU,GAAG,KAAS,MAAQ;CAEvD,IAAM,IAAe,OAAO,KAAa,WAAW,IAAW,IAEzD,IAAQ,EADD,KAAa,CACS,GAG7B,IAAQ,EAAM,WAAW,CAAkB,GAC3C,IAAO,EAAM,WAAW,CAAiB,GACzC,IAAa,MAAU,WAAW,iBAAiB,MAAU,YAAY,oBAAoB,gBAG7F,IAAW,EAAa,WAAW,IAAI,kBAAkB;CAE/D,OACE,kBAAC,GAAD;EACO;EACL,aAAU;EACV,WAAW,EACT,gEACA,GACA,EAAoB,IACpB,EAAM,IACN,EAAM,MACN,GACA,CACF;EACA,GAAI;EAEH;CACuB,CAAA;AAE9B,CAAC;AACD,EAAe,cAAA,EAAuC"}
|
|
1
|
+
{"version":3,"file":"avatar.js","names":[],"sources":["../../src/ui/avatar.tsx"],"sourcesContent":["'use client'\n\nimport * as AvatarPrimitive from \"@primitives/react-avatar\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { motion } from \"framer-motion\"\nimport * as React from \"react\"\n\nimport { MotionPreference } from '../motion/motion-preference'\nimport { Dot, type DotColor, type DotSize } from \"./dot\"\nimport { springs } from \"./lib/motion\"\nimport { cn } from \"./lib/utils\"\nimport { Skeleton } from \"./skeleton\"\n\n// ── Contexts so AvatarFallback can inherit shape & size from Avatar ──\ntype AvatarShape = 'circle' | 'square' | 'rounded'\ntype AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'\nconst AvatarShapeContext = React.createContext<AvatarShape>('circle')\nconst AvatarSizeContext = React.createContext<AvatarSize>('md')\n\nexport const avatarVariants = cva(\n 'relative flex shrink-0 overflow-hidden',\n {\n variants: {\n size: {\n xs: 'h-ds-xs w-ds-xs',\n sm: 'h-ds-sm w-ds-sm',\n md: 'h-ds-md w-ds-md',\n lg: 'h-ds-lg w-ds-lg',\n xl: 'h-ds-xl w-ds-xl',\n },\n shape: {\n circle: 'rounded-pill',\n square: 'rounded-none',\n rounded: 'rounded-control',\n },\n },\n defaultVariants: { size: 'md', shape: 'circle' },\n }\n)\n\nexport type AvatarStatus = 'online' | 'offline' | 'busy' | 'away'\n\nexport type AvatarRing = 'none' | 'lead' | 'admin' | 'client'\n\n// Presence status → shared Dot intent colour.\nconst statusDotColor: Record<AvatarStatus, DotColor> = {\n online: 'success',\n offline: 'neutral',\n busy: 'error',\n away: 'warning',\n}\n\nconst statusLabelMap: Record<AvatarStatus, string> = {\n online: 'Online',\n offline: 'Offline',\n busy: 'Busy',\n away: 'Away',\n}\n\n/** Avatar size → Dot size (the status dot scales with the avatar). */\nconst statusDotSize: Record<AvatarSize, DotSize> = {\n xs: 'xs',\n sm: 'sm',\n md: 'md',\n lg: 'lg',\n xl: 'lg',\n}\n\n// ── Role ring ───────────────────────────────────────────────────────────────\n\nconst ringColorMap: Record<Exclude<AvatarRing, 'none'>, string> = {\n lead: 'ring-accent-7',\n admin: 'ring-warning-7',\n client: 'ring-info-7',\n}\n\nconst ringShapeMap: Record<string, string> = {\n circle: 'rounded-pill',\n square: 'rounded-none',\n rounded: 'rounded-control',\n}\n\n// ── Fallback font sizes that scale with avatar size ─────────────────────────\nconst fallbackTextSizeMap: Record<AvatarSize, string> = {\n xs: 'text-body-xs',\n sm: 'text-body-xs',\n md: 'text-body-sm',\n lg: 'text-body-md',\n xl: 'text-heading-xs',\n}\n\n// ── Deterministic fallback colors ───────────────────────────────────────────\n\nconst FALLBACK_COLORS = [\n { bg: 'bg-accent-3', text: 'text-accent-11' },\n { bg: 'bg-success-3', text: 'text-success-11' },\n { bg: 'bg-warning-3', text: 'text-warning-11' },\n { bg: 'bg-error-3', text: 'text-error-11' },\n { bg: 'bg-info-3', text: 'text-info-11' },\n { bg: 'bg-category-teal-3', text: 'text-category-teal-11' },\n { bg: 'bg-category-indigo-3', text: 'text-category-indigo-11' },\n { bg: 'bg-category-cyan-3', text: 'text-category-cyan-11' },\n] as const\n\n/**\n * Simple string hash that produces a deterministic index into FALLBACK_COLORS.\n * Uses djb2 for a reasonable distribution with short strings.\n */\nfunction getFallbackColor(seed: string): (typeof FALLBACK_COLORS)[number] {\n let hash = 5381\n for (let i = 0; i < seed.length; i++) {\n hash = ((hash << 5) + hash + seed.charCodeAt(i)) | 0\n }\n const index = Math.abs(hash) % FALLBACK_COLORS.length\n return FALLBACK_COLORS[index]\n}\n\n/**\n * Props for Avatar — a user/entity image container with size, shape, and presence-status variants.\n *\n * **Sizes:** `xs` | `sm` | `md` (default) | `lg` | `xl` — the status dot scales with the avatar size.\n *\n * **Shapes:** `circle` (default, round) | `square` (sharp corners) | `rounded` (rounded corners, for bots/apps)\n *\n * **Status dot:** `status=\"online\"` (green) | `\"offline\"` (muted) | `\"busy\"` (red) | `\"away\"` (amber).\n * The dot renders with `role=\"img\"` and an accessible `aria-label` — it is not purely decorative.\n *\n * **Role ring:** `ring=\"lead\"` (accent) | `\"admin\"` (warning) | `\"client\"` (info) — a colored ring\n * around the avatar indicating the user's role.\n *\n * **Badge:** `badge={5}` (number) | `badge=\"dot\"` (notification dot) | `badge={<Icon />}` (custom).\n * Numbers > 99 display as \"99+\". Badge is hidden when `0` or `undefined`.\n *\n * **Loading:** `loading={true}` shows a pulse skeleton placeholder.\n *\n * **Children:** Use `<AvatarImage>` for the photo and `<AvatarFallback>` for initials when the image fails.\n *\n * @example\n * // User avatar with photo and fallback initials:\n * <Avatar size=\"md\">\n * <AvatarImage src={user.avatarUrl} alt={user.name} />\n * <AvatarFallback>JD</AvatarFallback>\n * </Avatar>\n *\n * @example\n * // Online presence indicator in a team roster:\n * <Avatar size=\"lg\" status=\"online\">\n * <AvatarImage src={user.photoUrl} alt={user.name} />\n * <AvatarFallback>{user.initials}</AvatarFallback>\n * </Avatar>\n *\n * @example\n * // Square shape for a bot/integration logo:\n * <Avatar shape=\"square\" size=\"xl\">\n * <AvatarImage src=\"/logos/github.png\" alt=\"GitHub\" />\n * </Avatar>\n * // These are just a few ways — feel free to combine props creatively!\n */\nexport interface AvatarProps\n extends Omit<React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>, 'children'>,\n VariantProps<typeof avatarVariants> {\n /** Optional status indicator displayed as a dot at the bottom-right corner */\n status?: AvatarStatus\n /** Role ring color indicator */\n ring?: AvatarRing\n /** Badge overlay: number, 'dot', or custom ReactNode */\n badge?: number | 'dot' | React.ReactNode\n /** Show loading skeleton instead of content */\n loading?: boolean\n children?: React.ReactNode\n}\n\nconst Avatar = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Root>,\n AvatarProps\n>(({ className, size, shape, status, ring, badge, loading, children, ...props }, ref) => {\n const resolvedShape = shape ?? 'circle'\n\n // Build ring classes for the outer wrapper\n const ringClasses = ring && ring !== 'none'\n ? cn('ring-2 ring-offset-2 ring-offset-surface-panel', ringColorMap[ring], ringShapeMap[resolvedShape])\n : undefined\n\n // Loading skeleton — early return\n if (loading) {\n return (\n <span ref={ref} className={cn('relative inline-flex shrink-0', ringClasses)}>\n <Skeleton\n className={cn(avatarVariants({ size, shape }))}\n data-slot=\"avatar-skeleton\"\n />\n </span>\n )\n }\n\n // Determine whether to render badge\n const showBadge = badge !== undefined && badge !== 0\n\n return (\n <MotionPreference>\n <AvatarShapeContext.Provider value={resolvedShape}>\n <AvatarSizeContext.Provider value={size ?? 'md'}>\n <span className={cn('relative inline-flex shrink-0', ringClasses)}>\n <AvatarPrimitive.Root\n ref={ref}\n className={cn(avatarVariants({ size, shape }), className)}\n {...props}\n >\n {children}\n </AvatarPrimitive.Root>\n {status && (\n <span\n className=\"absolute bottom-0 right-0\"\n role=\"img\"\n aria-label={statusLabelMap[status]}\n >\n {/* Shared Dot primitive: colour + contrast ring; wrapper owns position + a11y. */}\n <Dot color={statusDotColor[status]} size={statusDotSize[size ?? 'md']} withBorder aria-hidden />\n </span>\n )}\n {showBadge && (\n badge === 'dot' ? (\n <span\n className=\"absolute -right-0.5 -top-0.5 h-ds-03 w-ds-03 rounded-pill bg-error-9 ring-2 ring-surface-panel\"\n data-slot=\"avatar-badge-dot\"\n aria-hidden=\"true\"\n />\n ) : typeof badge === 'number' ? (\n <motion.span\n initial={{ scale: 0 }}\n animate={{ scale: 1 }}\n transition={springs.smooth}\n className=\"absolute -right-1 -top-1 flex min-w-ds-05 items-center justify-center rounded-pill bg-error-9 px-1 text-[10px] font-bold leading-[16px] text-error-fg ring-2 ring-surface-panel\"\n data-slot=\"avatar-badge\"\n role=\"status\"\n aria-label={`${badge > 99 ? '99+' : badge} notifications`}\n >\n {badge > 99 ? '99+' : badge}\n </motion.span>\n ) : (\n <span className=\"absolute -right-1 -top-1\" data-slot=\"avatar-badge-custom\">\n {badge}\n </span>\n )\n )}\n </span>\n </AvatarSizeContext.Provider>\n </AvatarShapeContext.Provider>\n </MotionPreference>\n )\n})\nAvatar.displayName = AvatarPrimitive.Root.displayName\n\nconst AvatarImage = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Image>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>\n>(({ className, ...props }, ref) => (\n <MotionPreference>\n <motion.span\n initial={{ scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={springs.smooth}\n className=\"absolute inset-0 h-full w-full\"\n >\n <AvatarPrimitive.Image\n ref={ref}\n className={cn(\"aspect-square h-full w-full\", className)}\n {...props}\n />\n </motion.span>\n </MotionPreference>\n))\nAvatarImage.displayName = AvatarPrimitive.Image.displayName\n\nexport interface AvatarFallbackProps\n extends React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback> {\n /**\n * Seed string for deterministic color selection.\n * Falls back to the text content of `children` if not provided.\n */\n colorSeed?: string\n}\n\nconst AvatarFallback = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Fallback>,\n AvatarFallbackProps\n>(({ className, colorSeed, children, ...props }, ref) => {\n // Derive seed: explicit colorSeed > children text content > empty string\n const childrenText = typeof children === 'string' ? children : ''\n const seed = colorSeed ?? childrenText\n const color = getFallbackColor(seed)\n\n // Inherit shape and size from parent Avatar via context\n const shape = React.useContext(AvatarShapeContext)\n const size = React.useContext(AvatarSizeContext)\n const shapeClass = shape === 'square' ? 'rounded-none' : shape === 'rounded' ? 'rounded-control' : 'rounded-pill'\n\n // Letter-spacing based on character count\n const tracking = childrenText.length === 1 ? 'tracking-wide' : 'tracking-normal'\n\n return (\n <AvatarPrimitive.Fallback\n ref={ref}\n data-slot=\"avatar-fallback\"\n className={cn(\n 'flex h-full w-full items-center justify-center font-semibold',\n shapeClass,\n fallbackTextSizeMap[size],\n color.bg,\n color.text,\n tracking,\n className,\n )}\n {...props}\n >\n {children}\n </AvatarPrimitive.Fallback>\n )\n})\nAvatarFallback.displayName = AvatarPrimitive.Fallback.displayName\n\nexport { Avatar, AvatarFallback,AvatarImage }\n"],"mappings":"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"}
|