@alfadocs/ui-kit-debug 0.66.0 → 0.67.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{agenda-card-Bl-SBiCh.js → agenda-card-BxSFkqgY.js} +2 -2
- package/dist/_chunks/{agenda-card-Bl-SBiCh.js.map → agenda-card-BxSFkqgY.js.map} +1 -1
- package/dist/_chunks/{agenda-tray-Bh1KfEOG.js → agenda-tray-T-BumlGZ.js} +2 -2
- package/dist/_chunks/{agenda-tray-Bh1KfEOG.js.map → agenda-tray-T-BumlGZ.js.map} +1 -1
- package/dist/_chunks/{ai-consent-banner-Btzmk8OH.js → ai-consent-banner-Dxtx_WAh.js} +2 -2
- package/dist/_chunks/{ai-consent-banner-Btzmk8OH.js.map → ai-consent-banner-Dxtx_WAh.js.map} +1 -1
- package/dist/_chunks/{ai-tools-rail-DAfaW8eA.js → ai-tools-rail-DfmewPUN.js} +57 -50
- package/dist/_chunks/ai-tools-rail-DfmewPUN.js.map +1 -0
- package/dist/_chunks/{alia-sidebar-CN8pA6c-.js → alia-sidebar-Ckv0yCKi.js} +2 -2
- package/dist/_chunks/{alia-sidebar-CN8pA6c-.js.map → alia-sidebar-Ckv0yCKi.js.map} +1 -1
- package/dist/_chunks/{anamnesis-card-qeLYRG79.js → anamnesis-card-N8pIKWuS.js} +2 -2
- package/dist/_chunks/{anamnesis-card-qeLYRG79.js.map → anamnesis-card-N8pIKWuS.js.map} +1 -1
- package/dist/_chunks/{antenatal-schedule-timeline-BfzFjEyb.js → antenatal-schedule-timeline-35ebkcZT.js} +2 -2
- package/dist/_chunks/{antenatal-schedule-timeline-BfzFjEyb.js.map → antenatal-schedule-timeline-35ebkcZT.js.map} +1 -1
- package/dist/_chunks/{appointment-tray-BQnJEora.js → appointment-tray-CQJ3Nbi5.js} +4 -4
- package/dist/_chunks/{appointment-tray-BQnJEora.js.map → appointment-tray-CQJ3Nbi5.js.map} +1 -1
- package/dist/_chunks/{badge-zsf5i5bH.js → badge-CqGsX32l.js} +46 -42
- package/dist/_chunks/badge-CqGsX32l.js.map +1 -0
- package/dist/_chunks/{bishop-score-DPN4Ched.js → bishop-score-CjsB9bM-.js} +2 -2
- package/dist/_chunks/{bishop-score-DPN4Ched.js.map → bishop-score-CjsB9bM-.js.map} +1 -1
- package/dist/_chunks/{bmi-calculator-DuUneHuZ.js → bmi-calculator-n-823_1V.js} +2 -2
- package/dist/_chunks/{bmi-calculator-DuUneHuZ.js.map → bmi-calculator-n-823_1V.js.map} +1 -1
- package/dist/_chunks/{care-plan-card-D42WD4-T.js → care-plan-card-CJei-nl9.js} +4 -4
- package/dist/_chunks/{care-plan-card-D42WD4-T.js.map → care-plan-card-CJei-nl9.js.map} +1 -1
- package/dist/_chunks/{care-plan-entry-card-BukNI7Uy.js → care-plan-entry-card-EmfrbHu8.js} +4 -4
- package/dist/_chunks/{care-plan-entry-card-BukNI7Uy.js.map → care-plan-entry-card-EmfrbHu8.js.map} +1 -1
- package/dist/_chunks/{clinical-note-card-BYo437dU.js → clinical-note-card-gtrxv6zn.js} +2 -2
- package/dist/_chunks/{clinical-note-card-BYo437dU.js.map → clinical-note-card-gtrxv6zn.js.map} +1 -1
- package/dist/_chunks/{color-picker-9tL7pz5y.js → color-picker-B7xsn6tX.js} +186 -167
- package/dist/_chunks/color-picker-B7xsn6tX.js.map +1 -0
- package/dist/_chunks/{contact-profile-card-CCeJmjbd.js → contact-profile-card-7BMB85T6.js} +2 -2
- package/dist/_chunks/{contact-profile-card-CCeJmjbd.js.map → contact-profile-card-7BMB85T6.js.map} +1 -1
- package/dist/_chunks/{cycle-calculator-D6LTmtQt.js → cycle-calculator-BF0ointe.js} +2 -2
- package/dist/_chunks/{cycle-calculator-D6LTmtQt.js.map → cycle-calculator-BF0ointe.js.map} +1 -1
- package/dist/_chunks/{dependent-selector-CRWgieHm.js → dependent-selector-DpzGtr_J.js} +2 -2
- package/dist/_chunks/{dependent-selector-CRWgieHm.js.map → dependent-selector-DpzGtr_J.js.map} +1 -1
- package/dist/_chunks/{document-scanner-biBS_f6c.js → document-scanner-D2qehl3-.js} +53 -53
- package/dist/_chunks/{document-scanner-biBS_f6c.js.map → document-scanner-D2qehl3-.js.map} +1 -1
- package/dist/_chunks/{due-date-calculator-CIG194vq.js → due-date-calculator-DU9AEWNy.js} +3 -3
- package/dist/_chunks/{due-date-calculator-CIG194vq.js.map → due-date-calculator-DU9AEWNy.js.map} +1 -1
- package/dist/_chunks/{editable-currency-cell-renderer-f3d0Rhue.js → editable-currency-cell-renderer-BVJ04DkB.js} +956 -897
- package/dist/_chunks/editable-currency-cell-renderer-BVJ04DkB.js.map +1 -0
- package/dist/_chunks/{fetal-weight-Xf8-ZoDy.js → fetal-weight-BVSzOhuR.js} +2 -2
- package/dist/_chunks/{fetal-weight-Xf8-ZoDy.js.map → fetal-weight-BVSzOhuR.js.map} +1 -1
- package/dist/_chunks/{gestational-age-calculator-BGsZaWXW.js → gestational-age-calculator-DBlFdoiP.js} +3 -3
- package/dist/_chunks/{gestational-age-calculator-BGsZaWXW.js.map → gestational-age-calculator-DBlFdoiP.js.map} +1 -1
- package/dist/_chunks/{hcg-doubling-LH5i6oM7.js → hcg-doubling-if4Q8aSX.js} +2 -2
- package/dist/_chunks/{hcg-doubling-LH5i6oM7.js.map → hcg-doubling-if4Q8aSX.js.map} +1 -1
- package/dist/_chunks/{marketplace-app-shell-Cou6XnMJ.js → marketplace-app-shell-Bu-HD3fy.js} +3 -3
- package/dist/_chunks/{marketplace-app-shell-Cou6XnMJ.js.map → marketplace-app-shell-Bu-HD3fy.js.map} +1 -1
- package/dist/_chunks/{message-card-Bgcvfj6-.js → message-card-Bx4GmLvf.js} +9 -9
- package/dist/_chunks/{message-card-Bgcvfj6-.js.map → message-card-Bx4GmLvf.js.map} +1 -1
- package/dist/_chunks/{message-tray-saAVMeHP.js → message-tray-CVyJajVJ.js} +2 -2
- package/dist/_chunks/{message-tray-saAVMeHP.js.map → message-tray-CVyJajVJ.js.map} +1 -1
- package/dist/_chunks/{operator-hero-CM8949Hd.js → operator-hero-f_KaRhw5.js} +2 -2
- package/dist/_chunks/{operator-hero-CM8949Hd.js.map → operator-hero-f_KaRhw5.js.map} +1 -1
- package/dist/_chunks/{patient-search-Bw9ONucF.js → patient-search-DR9XUYRQ.js} +2 -2
- package/dist/_chunks/{patient-search-Bw9ONucF.js.map → patient-search-DR9XUYRQ.js.map} +1 -1
- package/dist/_chunks/{patient-shell-Tgpv0HND.js → patient-shell-DrV_iekt.js} +2 -2
- package/dist/_chunks/{patient-shell-Tgpv0HND.js.map → patient-shell-DrV_iekt.js.map} +1 -1
- package/dist/_chunks/{patient-summary-card-Bgso0p_l.js → patient-summary-card-ByfIU8N0.js} +4 -4
- package/dist/_chunks/{patient-summary-card-Bgso0p_l.js.map → patient-summary-card-ByfIU8N0.js.map} +1 -1
- package/dist/_chunks/{payment-request-card-DBz3hVDz.js → payment-request-card-yTjzKQCU.js} +3 -3
- package/dist/_chunks/{payment-request-card-DBz3hVDz.js.map → payment-request-card-yTjzKQCU.js.map} +1 -1
- package/dist/_chunks/{periodontal-chart-card-AYyHtU9K.js → periodontal-chart-card-Dh3KgvYG.js} +2 -2
- package/dist/_chunks/{periodontal-chart-card-AYyHtU9K.js.map → periodontal-chart-card-Dh3KgvYG.js.map} +1 -1
- package/dist/_chunks/{practice-results-CVAgY2RZ.js → practice-results-DND2SAt7.js} +2 -2
- package/dist/_chunks/{practice-results-CVAgY2RZ.js.map → practice-results-DND2SAt7.js.map} +1 -1
- package/dist/_chunks/{pregnancy-dating-f9aJbiAk.js → pregnancy-dating-QY-sqpvj.js} +3 -3
- package/dist/_chunks/{pregnancy-dating-f9aJbiAk.js.map → pregnancy-dating-QY-sqpvj.js.map} +1 -1
- package/dist/_chunks/{pregnancy-weight-gain-BMRBeA8V.js → pregnancy-weight-gain-DOJXXNYP.js} +2 -2
- package/dist/_chunks/{pregnancy-weight-gain-BMRBeA8V.js.map → pregnancy-weight-gain-DOJXXNYP.js.map} +1 -1
- package/dist/_chunks/rich-text-editor-BOQr5lHx.js +1970 -0
- package/dist/_chunks/rich-text-editor-BOQr5lHx.js.map +1 -0
- package/dist/_chunks/{scroll-area-BWqCkEGz.js → scroll-area-eccd_Uf-.js} +38 -28
- package/dist/_chunks/scroll-area-eccd_Uf-.js.map +1 -0
- package/dist/_chunks/{sidebar-BFwbx74W.js → sidebar-CGjIk_FQ.js} +25 -22
- package/dist/_chunks/sidebar-CGjIk_FQ.js.map +1 -0
- package/dist/_chunks/{suggestion-chip-C4kxWUIs.js → suggestion-chip-Bk4PmYTg.js} +30 -30
- package/dist/_chunks/suggestion-chip-Bk4PmYTg.js.map +1 -0
- package/dist/_chunks/{tab-bar-Xetknddo.js → tab-bar-B1ovILzh.js} +2 -2
- package/dist/_chunks/{tab-bar-Xetknddo.js.map → tab-bar-B1ovILzh.js.map} +1 -1
- package/dist/_chunks/{tag-CdA0s_VV.js → tag-BQXwuJq1.js} +41 -38
- package/dist/_chunks/tag-BQXwuJq1.js.map +1 -0
- package/dist/_chunks/{transaction-chip-BZCa6XDn.js → transaction-chip-BrW8P50O.js} +19 -19
- package/dist/_chunks/transaction-chip-BrW8P50O.js.map +1 -0
- package/dist/_chunks/{workflow-map-Bt4Of5dT.js → workflow-map-JAZryZJr.js} +2 -2
- package/dist/_chunks/{workflow-map-Bt4Of5dT.js.map → workflow-map-JAZryZJr.js.map} +1 -1
- package/dist/agent-catalog.json +1 -1
- package/dist/components/agenda-card/index.js +1 -1
- package/dist/components/agenda-tray/index.js +1 -1
- package/dist/components/ai-consent-banner/index.js +1 -1
- package/dist/components/ai-tools-rail/ai-tools-rail.d.ts.map +1 -1
- package/dist/components/ai-tools-rail/index.js +1 -1
- package/dist/components/anamnesis-card/index.js +1 -1
- package/dist/components/appointment-card/index.js +1 -1
- package/dist/components/badge/badge.d.ts.map +1 -1
- package/dist/components/badge/index.js +1 -1
- package/dist/components/bishop-score/index.js +1 -1
- package/dist/components/bmi-calculator/index.js +1 -1
- package/dist/components/care-plan-card/index.js +1 -1
- package/dist/components/care-plan-entry-card/index.js +1 -1
- package/dist/components/clinical-note-card/index.js +1 -1
- package/dist/components/color-picker/color-picker.d.ts.map +1 -1
- package/dist/components/color-picker/index.js +1 -1
- package/dist/components/contact-profile-card/index.js +1 -1
- package/dist/components/cycle-calculator/index.js +1 -1
- package/dist/components/data-table/cell-renderers/actions-cell-renderer.d.ts +16 -0
- package/dist/components/data-table/cell-renderers/actions-cell-renderer.d.ts.map +1 -1
- package/dist/components/data-table/cell-renderers/tooth-cell-renderer.d.ts +12 -0
- package/dist/components/data-table/cell-renderers/tooth-cell-renderer.d.ts.map +1 -0
- package/dist/components/data-table/data-table.d.ts +1 -1
- package/dist/components/data-table/index.d.ts +2 -0
- package/dist/components/data-table/index.d.ts.map +1 -1
- package/dist/components/data-table/index.js +13 -12
- package/dist/components/data-table/toolbar.d.ts +5 -1
- package/dist/components/data-table/toolbar.d.ts.map +1 -1
- package/dist/components/dependent-selector/index.js +1 -1
- package/dist/components/document-scanner/index.js +1 -1
- package/dist/components/due-date-calculator/index.js +2 -2
- package/dist/components/fetal-weight/index.js +1 -1
- package/dist/components/gestational-age-calculator/index.js +1 -1
- package/dist/components/hcg-doubling/index.js +1 -1
- package/dist/components/message-card/index.js +1 -1
- package/dist/components/message-tray/index.js +1 -1
- package/dist/components/operator-hero/index.js +1 -1
- package/dist/components/patient-search/index.js +1 -1
- package/dist/components/patient-summary-card/index.js +1 -1
- package/dist/components/payment-card/index.js +1 -1
- package/dist/components/periodontal-chart-card/index.js +1 -1
- package/dist/components/practice-results/index.js +1 -1
- package/dist/components/pregnancy-dating/index.js +1 -1
- package/dist/components/pregnancy-weight-gain/index.js +1 -1
- package/dist/components/rich-text-editor/editor-toolbar.d.ts +25 -1
- package/dist/components/rich-text-editor/editor-toolbar.d.ts.map +1 -1
- package/dist/components/rich-text-editor/index.js +1 -1
- package/dist/components/rich-text-editor/rich-text-editor.d.ts +2 -0
- package/dist/components/rich-text-editor/rich-text-editor.d.ts.map +1 -1
- package/dist/components/scroll-area/index.js +1 -1
- package/dist/components/scroll-area/scroll-area.d.ts.map +1 -1
- package/dist/components/sidebar/index.js +1 -1
- package/dist/components/sidebar/sidebar.d.ts.map +1 -1
- package/dist/components/suggestion-chip/index.js +1 -1
- package/dist/components/tab-bar/index.js +1 -1
- package/dist/components/tag/index.js +1 -1
- package/dist/components/tag/tag.d.ts.map +1 -1
- package/dist/components/transaction-chip/index.js +1 -1
- package/dist/components/transaction-chip/transaction-chip.d.ts.map +1 -1
- package/dist/components/workflow/index.js +1 -1
- package/dist/i18n/locales/ar.d.ts +10 -0
- package/dist/i18n/locales/ar.d.ts.map +1 -1
- package/dist/i18n/locales/ar.js +11 -1
- package/dist/i18n/locales/ar.js.map +1 -1
- package/dist/i18n/locales/de.d.ts +10 -0
- package/dist/i18n/locales/de.d.ts.map +1 -1
- package/dist/i18n/locales/de.js +11 -1
- package/dist/i18n/locales/de.js.map +1 -1
- package/dist/i18n/locales/el.d.ts +10 -0
- package/dist/i18n/locales/el.d.ts.map +1 -1
- package/dist/i18n/locales/el.js +11 -1
- package/dist/i18n/locales/el.js.map +1 -1
- package/dist/i18n/locales/en.d.ts +10 -0
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +11 -1
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +10 -0
- package/dist/i18n/locales/es.d.ts.map +1 -1
- package/dist/i18n/locales/es.js +11 -1
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +10 -0
- package/dist/i18n/locales/fr.d.ts.map +1 -1
- package/dist/i18n/locales/fr.js +11 -1
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hi.d.ts +10 -0
- package/dist/i18n/locales/hi.d.ts.map +1 -1
- package/dist/i18n/locales/hi.js +11 -1
- package/dist/i18n/locales/hi.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +10 -0
- package/dist/i18n/locales/it.d.ts.map +1 -1
- package/dist/i18n/locales/it.js +11 -1
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/ja.d.ts +10 -0
- package/dist/i18n/locales/ja.d.ts.map +1 -1
- package/dist/i18n/locales/ja.js +11 -1
- package/dist/i18n/locales/ja.js.map +1 -1
- package/dist/i18n/locales/nl.d.ts +10 -0
- package/dist/i18n/locales/nl.d.ts.map +1 -1
- package/dist/i18n/locales/nl.js +9 -1
- package/dist/i18n/locales/nl.js.map +1 -1
- package/dist/i18n/locales/pl.d.ts +10 -0
- package/dist/i18n/locales/pl.d.ts.map +1 -1
- package/dist/i18n/locales/pl.js +11 -1
- package/dist/i18n/locales/pl.js.map +1 -1
- package/dist/i18n/locales/pt.d.ts +10 -0
- package/dist/i18n/locales/pt.d.ts.map +1 -1
- package/dist/i18n/locales/pt.js +11 -1
- package/dist/i18n/locales/pt.js.map +1 -1
- package/dist/i18n/locales/ro.d.ts +10 -0
- package/dist/i18n/locales/ro.d.ts.map +1 -1
- package/dist/i18n/locales/ro.js +11 -1
- package/dist/i18n/locales/ro.js.map +1 -1
- package/dist/i18n/locales/ru.d.ts +10 -0
- package/dist/i18n/locales/ru.d.ts.map +1 -1
- package/dist/i18n/locales/ru.js +11 -1
- package/dist/i18n/locales/ru.js.map +1 -1
- package/dist/i18n/locales/sq.d.ts +10 -0
- package/dist/i18n/locales/sq.d.ts.map +1 -1
- package/dist/i18n/locales/sq.js +11 -1
- package/dist/i18n/locales/sq.js.map +1 -1
- package/dist/i18n/locales/sv.d.ts +10 -0
- package/dist/i18n/locales/sv.d.ts.map +1 -1
- package/dist/i18n/locales/sv.js +9 -1
- package/dist/i18n/locales/sv.js.map +1 -1
- package/dist/i18n/locales/tr.d.ts +10 -0
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/locales/tr.js +11 -1
- package/dist/i18n/locales/tr.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +10 -0
- package/dist/i18n/locales/zh.d.ts.map +1 -1
- package/dist/i18n/locales/zh.js +9 -1
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/index.js +508 -507
- package/dist/locales/ar.json +11 -1
- package/dist/locales/de.json +11 -1
- package/dist/locales/el.json +11 -1
- package/dist/locales/en.json +11 -1
- package/dist/locales/es.json +11 -1
- package/dist/locales/fr.json +11 -1
- package/dist/locales/hi.json +11 -1
- package/dist/locales/it.json +11 -1
- package/dist/locales/ja.json +11 -1
- package/dist/locales/nl.json +11 -1
- package/dist/locales/pl.json +11 -1
- package/dist/locales/pt.json +11 -1
- package/dist/locales/ro.json +11 -1
- package/dist/locales/ru.json +11 -1
- package/dist/locales/sq.json +11 -1
- package/dist/locales/sv.json +11 -1
- package/dist/locales/tr.json +11 -1
- package/dist/locales/zh.json +11 -1
- package/dist/patterns/alia-assistant/index.js +1 -1
- package/dist/patterns/marketplace-app-shell/index.js +1 -1
- package/dist/patterns/patient-shell/index.js +1 -1
- package/dist/tokens.css +6 -3
- package/package.json +1 -1
- package/dist/_chunks/ai-tools-rail-DAfaW8eA.js.map +0 -1
- package/dist/_chunks/badge-zsf5i5bH.js.map +0 -1
- package/dist/_chunks/color-picker-9tL7pz5y.js.map +0 -1
- package/dist/_chunks/editable-currency-cell-renderer-f3d0Rhue.js.map +0 -1
- package/dist/_chunks/rich-text-editor-B5XQNxe8.js +0 -1586
- package/dist/_chunks/rich-text-editor-B5XQNxe8.js.map +0 -1
- package/dist/_chunks/scroll-area-BWqCkEGz.js.map +0 -1
- package/dist/_chunks/sidebar-BFwbx74W.js.map +0 -1
- package/dist/_chunks/suggestion-chip-C4kxWUIs.js.map +0 -1
- package/dist/_chunks/tag-CdA0s_VV.js.map +0 -1
- package/dist/_chunks/transaction-chip-BZCa6XDn.js.map +0 -1
|
@@ -3,7 +3,7 @@ import { forwardRef as h } from "react";
|
|
|
3
3
|
import { c as x } from "./index-D2ZczOXr.js";
|
|
4
4
|
import { useTranslation as y } from "react-i18next";
|
|
5
5
|
import { A as N } from "./avatar-BNQNhoyL.js";
|
|
6
|
-
import { B as C } from "./badge-
|
|
6
|
+
import { B as C } from "./badge-CqGsX32l.js";
|
|
7
7
|
import { i as w } from "./is-safe-url-DkETxeHz.js";
|
|
8
8
|
import { C as k } from "./chevron-right-BrpYejk0.js";
|
|
9
9
|
const L = x(
|
|
@@ -144,4 +144,4 @@ z.displayName = "AgendaCard";
|
|
|
144
144
|
export {
|
|
145
145
|
z as A
|
|
146
146
|
};
|
|
147
|
-
//# sourceMappingURL=agenda-card-
|
|
147
|
+
//# sourceMappingURL=agenda-card-BxSFkqgY.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agenda-card-Bl-SBiCh.js","sources":["../../src/components/agenda-card/agenda-card.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { ChevronRight } from 'lucide-react';\nimport { Avatar } from '../avatar/avatar';\nimport { Badge } from '../badge/badge';\nimport { isSafeEntityUrl } from '../_shared/is-safe-url';\n\n// Back-compat alias — the URL guard now lives in the shared entity-card\n// helper. Existing consumers (and this dir's tests) import isSafeAgendaUrl.\nexport { isSafeEntityUrl as isSafeAgendaUrl } from '../_shared/is-safe-url';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport type AppointmentStatus =\n | 'confirmed'\n | 'pending'\n | 'cancelled'\n | 'absent';\n\nexport interface AgendaItem {\n /** Unique identifier for the appointment. */\n id: string;\n /** Display time string (e.g. \"09:00\"). Localised by the consumer. */\n time: string;\n /**\n * Localised date eyebrow (e.g. \"Thu 12 Jun\") rendered under the time —\n * for agendas spanning more than today (upcoming-appointments queues).\n */\n dateLabel?: string;\n /** Patient identity — drives the avatar's initials + accessible name. */\n patient: { name: string; avatarUrl?: string };\n /** Treatment / appointment type — short localised label. */\n treatment?: string;\n /**\n * Context line under the treatment (e.g. \"Dr. Bianchi · Chair 2\").\n * Localised and pre-joined by the consumer.\n */\n meta?: string;\n /** Free-text booking note — muted body line, clamped. */\n note?: string;\n /** Lifecycle state — drives a trailing status chip. */\n status?: AppointmentStatus;\n /** Optional deep link — when present the row is an anchor. */\n url?: string;\n}\n\nexport interface AgendaCardProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'onClick' | 'role' | 'title'>,\n VariantProps<typeof agendaCardVariants> {\n /** The appointment to render. */\n item: AgendaItem;\n /** Visual density. */\n size?: 'sm' | 'md';\n /** Fires when the row is activated. */\n onActivate?: (item: AgendaItem) => void;\n /**\n * Trailing per-row action toolbar. Rendered above the stretched-link\n * overlay so the controls stay clickable inside an interactive row.\n */\n actions?: ReactNode;\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst agendaCardVariants = cva(\n [\n 'ds:relative ds:flex ds:items-center ds:gap-[var(--spacing-sm)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:transition-colors',\n 'ds:motion-reduce:transition-none',\n 'ds:text-start ds:group',\n 'ds:forced-colors:border ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:p-[var(--spacing-sm)]',\n md: 'ds:p-[var(--spacing-md)]',\n },\n interactive: {\n true: 'ds:hover:bg-[color:var(--muted)]/40 ds:cursor-pointer',\n false: '',\n },\n },\n defaultVariants: {\n size: 'sm',\n interactive: false,\n },\n },\n);\n\nconst stretchedLinkClass = [\n 'ds:focus-visible:outline-none',\n \"ds:after:content-[''] ds:after:absolute ds:after:inset-0 ds:after:rounded-[var(--radius-sm)]\",\n 'ds:after:pointer-events-auto',\n 'ds:focus-visible:after:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:after:outline-solid',\n 'ds:focus-visible:after:outline-[color:var(--ring)]',\n 'ds:focus-visible:after:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:after:outline-[CanvasText]',\n].join(' ');\n\nconst STATUS_TONE: Record<AppointmentStatus, 'success' | 'warning' | 'error'> =\n {\n confirmed: 'success',\n pending: 'warning',\n cancelled: 'error',\n absent: 'error',\n };\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const AgendaCard = forwardRef<HTMLDivElement, AgendaCardProps>(\n ({ item, size = 'sm', onActivate, actions, className, ...rest }, ref) => {\n const { t } = useTranslation();\n const interactive = !!onActivate;\n const hasSafeUrl = !!item.url && isSafeEntityUrl(item.url);\n const baseLabel = t('agendaCard.itemLabel', {\n time: item.time,\n patient: item.patient.name,\n treatment: item.treatment ?? '',\n defaultValue: '{{time}} · {{patient}}{{treatment, prepend, \" · \"}}',\n });\n // dateLabel renders inside the aria-hidden time column, so it must be\n // prepended here or multi-day rows get identical accessible names.\n const ariaLabel = item.dateLabel\n ? `${item.dateLabel} · ${baseLabel}`\n : baseLabel;\n\n const titleNode = (\n <span className=\"ds:flex-1 ds:min-w-0 ds:truncate type-body-sm ds:text-[color:var(--foreground)]\">\n {item.patient.name}\n </span>\n );\n\n let activator: ReactNode;\n if (interactive && hasSafeUrl) {\n activator = (\n <a\n href={item.url}\n aria-label={ariaLabel}\n className={stretchedLinkClass + ' ds:contents'}\n onClick={(e) => {\n if (e.defaultPrevented || e.metaKey || e.ctrlKey || e.shiftKey)\n return;\n onActivate?.(item);\n }}\n >\n {titleNode}\n </a>\n );\n } else if (interactive) {\n activator = (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n className={\n stretchedLinkClass +\n ' ds:contents ds:bg-transparent ds:border-0 ds:p-0 ds:text-start'\n }\n onClick={() => onActivate?.(item)}\n >\n {titleNode}\n </button>\n );\n } else {\n activator = titleNode;\n }\n\n return (\n <div\n ref={ref}\n role=\"listitem\"\n data-component=\"agenda-card\"\n data-component-id={item.id}\n data-status={item.status ?? 'confirmed'}\n className={agendaCardVariants({ size, interactive, className })}\n {...rest}\n >\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-flex ds:flex-col ds:w-12 ds:shrink-0 type-body-sm ds:font-medium ds:text-[color:var(--foreground)] ds:tabular-nums\"\n >\n {item.time}\n {item.dateLabel ? (\n <span className=\"type-eyebrow ds:font-normal ds:text-[color:var(--muted-foreground)]\">\n {item.dateLabel}\n </span>\n ) : null}\n </span>\n\n <Avatar\n name={item.patient.name}\n src={item.patient.avatarUrl}\n size={size === 'md' ? 'md' : 'sm'}\n className=\"ds:shrink-0\"\n aria-hidden=\"true\"\n role=\"presentation\"\n aria-label={undefined}\n />\n\n <div className=\"ds:flex-1 ds:min-w-0 ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n {activator}\n {item.treatment ? (\n <span className=\"type-eyebrow ds:text-[color:var(--muted-foreground)] ds:truncate\">\n {item.treatment}\n </span>\n ) : null}\n {item.meta ? (\n <span className=\"type-eyebrow ds:text-[color:var(--muted-foreground)] ds:truncate\">\n {item.meta}\n </span>\n ) : null}\n {item.note ? (\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)] ds:line-clamp-2\">\n {item.note}\n </span>\n ) : null}\n </div>\n\n {actions ? (\n // Above the stretched-link overlay so the buttons stay clickable.\n <span className=\"ds:relative ds:z-[1] ds:flex ds:items-center ds:gap-[var(--spacing-2xs)] ds:shrink-0\">\n {actions}\n </span>\n ) : null}\n\n {item.status && item.status !== 'confirmed' ? (\n <Badge\n variant={STATUS_TONE[item.status]}\n size=\"sm\"\n withDot\n className=\"ds:shrink-0\"\n >\n {t(`agendaCard.status.${item.status}`, item.status)}\n </Badge>\n ) : null}\n\n {interactive ? (\n <ChevronRight\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:shrink-0 ds:text-[color:var(--muted-foreground)] ds:opacity-0 ds:transition-opacity ds:motion-reduce:transition-none ds:group-hover:opacity-100 ds:group-focus-within:opacity-100 ds:rtl:rotate-180\"\n />\n ) : null}\n </div>\n );\n },\n);\n\nAgendaCard.displayName = 'AgendaCard';\n"],"names":["agendaCardVariants","cva","stretchedLinkClass","STATUS_TONE","AgendaCard","forwardRef","item","size","onActivate","actions","className","rest","ref","t","useTranslation","interactive","hasSafeUrl","isSafeEntityUrl","baseLabel","ariaLabel","titleNode","jsx","activator","e","jsxs","Avatar","Badge","ChevronRight"],"mappings":";;;;;;;;AAsEA,MAAMA,IAAqBC;AAAA,EACzB;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,EACA,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MAAA;AAAA,MAEN,aAAa;AAAA,QACX,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,IACT;AAAA,IAEF,iBAAiB;AAAA,MACf,MAAM;AAAA,MACN,aAAa;AAAA,IAAA;AAAA,EACf;AAEJ,GAEMC,IAAqB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAEJC,IACJ;AAAA,EACE,WAAW;AAAA,EACX,SAAS;AAAA,EACT,WAAW;AAAA,EACX,QAAQ;AACV,GAMWC,IAAaC;AAAA,EACxB,CAAC,EAAE,MAAAC,GAAM,MAAAC,IAAO,MAAM,YAAAC,GAAY,SAAAC,GAAS,WAAAC,GAAW,GAAGC,EAAA,GAAQC,MAAQ;AACvE,UAAM,EAAE,GAAAC,EAAA,IAAMC,EAAA,GACRC,IAAc,CAAC,CAACP,GAChBQ,IAAa,CAAC,CAACV,EAAK,OAAOW,EAAgBX,EAAK,GAAG,GACnDY,IAAYL,EAAE,wBAAwB;AAAA,MAC1C,MAAMP,EAAK;AAAA,MACX,SAASA,EAAK,QAAQ;AAAA,MACtB,WAAWA,EAAK,aAAa;AAAA,MAC7B,cAAc;AAAA,IAAA,CACf,GAGKa,IAAYb,EAAK,YACnB,GAAGA,EAAK,SAAS,MAAMY,CAAS,KAChCA,GAEEE,IACJ,gBAAAC,EAAC,QAAA,EAAK,WAAU,mFACb,UAAAf,EAAK,QAAQ,MAChB;AAGF,QAAIgB;AACJ,WAAIP,KAAeC,IACjBM,IACE,gBAAAD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAMf,EAAK;AAAA,QACX,cAAYa;AAAA,QACZ,WAAWjB,IAAqB;AAAA,QAChC,SAAS,CAACqB,MAAM;AACd,UAAIA,EAAE,oBAAoBA,EAAE,WAAWA,EAAE,WAAWA,EAAE,YAEtDf,KAAA,QAAAA,EAAaF;AAAA,QACf;AAAA,QAEC,UAAAc;AAAA,MAAA;AAAA,IAAA,IAGIL,IACTO,IACE,gBAAAD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAYF;AAAA,QACZ,WACEjB,IACA;AAAA,QAEF,SAAS,MAAMM,KAAA,gBAAAA,EAAaF;AAAA,QAE3B,UAAAc;AAAA,MAAA;AAAA,IAAA,IAILE,IAAYF,GAIZ,gBAAAI;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAZ;AAAA,QACA,MAAK;AAAA,QACL,kBAAe;AAAA,QACf,qBAAmBN,EAAK;AAAA,QACxB,eAAaA,EAAK,UAAU;AAAA,QAC5B,WAAWN,EAAmB,EAAE,MAAAO,GAAM,aAAAQ,GAAa,WAAAL,GAAW;AAAA,QAC7D,GAAGC;AAAA,QAEJ,UAAA;AAAA,UAAA,gBAAAa;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,eAAY;AAAA,cACZ,WAAU;AAAA,cAET,UAAA;AAAA,gBAAAlB,EAAK;AAAA,gBACLA,EAAK,YACJ,gBAAAe,EAAC,QAAA,EAAK,WAAU,uEACb,UAAAf,EAAK,WACR,IACE;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGN,gBAAAe;AAAA,YAACI;AAAA,YAAA;AAAA,cACC,MAAMnB,EAAK,QAAQ;AAAA,cACnB,KAAKA,EAAK,QAAQ;AAAA,cAClB,MAAMC,MAAS,OAAO,OAAO;AAAA,cAC7B,WAAU;AAAA,cACV,eAAY;AAAA,cACZ,MAAK;AAAA,cACL,cAAY;AAAA,YAAA;AAAA,UAAA;AAAA,UAGd,gBAAAiB,EAAC,OAAA,EAAI,WAAU,wEACZ,UAAA;AAAA,YAAAF;AAAA,YACAhB,EAAK,YACJ,gBAAAe,EAAC,QAAA,EAAK,WAAU,oEACb,UAAAf,EAAK,WACR,IACE;AAAA,YACHA,EAAK,OACJ,gBAAAe,EAAC,QAAA,EAAK,WAAU,oEACb,UAAAf,EAAK,MACR,IACE;AAAA,YACHA,EAAK,OACJ,gBAAAe,EAAC,QAAA,EAAK,WAAU,wEACb,UAAAf,EAAK,MACR,IACE;AAAA,UAAA,GACN;AAAA,UAECG;AAAA;AAAA,YAEC,gBAAAY,EAAC,QAAA,EAAK,WAAU,wFACb,UAAAZ,EAAA,CACH;AAAA,cACE;AAAA,UAEHH,EAAK,UAAUA,EAAK,WAAW,cAC9B,gBAAAe;AAAA,YAACK;AAAA,YAAA;AAAA,cACC,SAASvB,EAAYG,EAAK,MAAM;AAAA,cAChC,MAAK;AAAA,cACL,SAAO;AAAA,cACP,WAAU;AAAA,cAET,YAAE,qBAAqBA,EAAK,MAAM,IAAIA,EAAK,MAAM;AAAA,YAAA;AAAA,UAAA,IAElD;AAAA,UAEHS,IACC,gBAAAM;AAAA,YAACM;AAAA,YAAA;AAAA,cACC,eAAY;AAAA,cACZ,WAAU;AAAA,YAAA;AAAA,UAAA,IAEV;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AACF;AAEAvB,EAAW,cAAc;"}
|
|
1
|
+
{"version":3,"file":"agenda-card-BxSFkqgY.js","sources":["../../src/components/agenda-card/agenda-card.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { ChevronRight } from 'lucide-react';\nimport { Avatar } from '../avatar/avatar';\nimport { Badge } from '../badge/badge';\nimport { isSafeEntityUrl } from '../_shared/is-safe-url';\n\n// Back-compat alias — the URL guard now lives in the shared entity-card\n// helper. Existing consumers (and this dir's tests) import isSafeAgendaUrl.\nexport { isSafeEntityUrl as isSafeAgendaUrl } from '../_shared/is-safe-url';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport type AppointmentStatus =\n | 'confirmed'\n | 'pending'\n | 'cancelled'\n | 'absent';\n\nexport interface AgendaItem {\n /** Unique identifier for the appointment. */\n id: string;\n /** Display time string (e.g. \"09:00\"). Localised by the consumer. */\n time: string;\n /**\n * Localised date eyebrow (e.g. \"Thu 12 Jun\") rendered under the time —\n * for agendas spanning more than today (upcoming-appointments queues).\n */\n dateLabel?: string;\n /** Patient identity — drives the avatar's initials + accessible name. */\n patient: { name: string; avatarUrl?: string };\n /** Treatment / appointment type — short localised label. */\n treatment?: string;\n /**\n * Context line under the treatment (e.g. \"Dr. Bianchi · Chair 2\").\n * Localised and pre-joined by the consumer.\n */\n meta?: string;\n /** Free-text booking note — muted body line, clamped. */\n note?: string;\n /** Lifecycle state — drives a trailing status chip. */\n status?: AppointmentStatus;\n /** Optional deep link — when present the row is an anchor. */\n url?: string;\n}\n\nexport interface AgendaCardProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'onClick' | 'role' | 'title'>,\n VariantProps<typeof agendaCardVariants> {\n /** The appointment to render. */\n item: AgendaItem;\n /** Visual density. */\n size?: 'sm' | 'md';\n /** Fires when the row is activated. */\n onActivate?: (item: AgendaItem) => void;\n /**\n * Trailing per-row action toolbar. Rendered above the stretched-link\n * overlay so the controls stay clickable inside an interactive row.\n */\n actions?: ReactNode;\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst agendaCardVariants = cva(\n [\n 'ds:relative ds:flex ds:items-center ds:gap-[var(--spacing-sm)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:transition-colors',\n 'ds:motion-reduce:transition-none',\n 'ds:text-start ds:group',\n 'ds:forced-colors:border ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:p-[var(--spacing-sm)]',\n md: 'ds:p-[var(--spacing-md)]',\n },\n interactive: {\n true: 'ds:hover:bg-[color:var(--muted)]/40 ds:cursor-pointer',\n false: '',\n },\n },\n defaultVariants: {\n size: 'sm',\n interactive: false,\n },\n },\n);\n\nconst stretchedLinkClass = [\n 'ds:focus-visible:outline-none',\n \"ds:after:content-[''] ds:after:absolute ds:after:inset-0 ds:after:rounded-[var(--radius-sm)]\",\n 'ds:after:pointer-events-auto',\n 'ds:focus-visible:after:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:after:outline-solid',\n 'ds:focus-visible:after:outline-[color:var(--ring)]',\n 'ds:focus-visible:after:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:after:outline-[CanvasText]',\n].join(' ');\n\nconst STATUS_TONE: Record<AppointmentStatus, 'success' | 'warning' | 'error'> =\n {\n confirmed: 'success',\n pending: 'warning',\n cancelled: 'error',\n absent: 'error',\n };\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const AgendaCard = forwardRef<HTMLDivElement, AgendaCardProps>(\n ({ item, size = 'sm', onActivate, actions, className, ...rest }, ref) => {\n const { t } = useTranslation();\n const interactive = !!onActivate;\n const hasSafeUrl = !!item.url && isSafeEntityUrl(item.url);\n const baseLabel = t('agendaCard.itemLabel', {\n time: item.time,\n patient: item.patient.name,\n treatment: item.treatment ?? '',\n defaultValue: '{{time}} · {{patient}}{{treatment, prepend, \" · \"}}',\n });\n // dateLabel renders inside the aria-hidden time column, so it must be\n // prepended here or multi-day rows get identical accessible names.\n const ariaLabel = item.dateLabel\n ? `${item.dateLabel} · ${baseLabel}`\n : baseLabel;\n\n const titleNode = (\n <span className=\"ds:flex-1 ds:min-w-0 ds:truncate type-body-sm ds:text-[color:var(--foreground)]\">\n {item.patient.name}\n </span>\n );\n\n let activator: ReactNode;\n if (interactive && hasSafeUrl) {\n activator = (\n <a\n href={item.url}\n aria-label={ariaLabel}\n className={stretchedLinkClass + ' ds:contents'}\n onClick={(e) => {\n if (e.defaultPrevented || e.metaKey || e.ctrlKey || e.shiftKey)\n return;\n onActivate?.(item);\n }}\n >\n {titleNode}\n </a>\n );\n } else if (interactive) {\n activator = (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n className={\n stretchedLinkClass +\n ' ds:contents ds:bg-transparent ds:border-0 ds:p-0 ds:text-start'\n }\n onClick={() => onActivate?.(item)}\n >\n {titleNode}\n </button>\n );\n } else {\n activator = titleNode;\n }\n\n return (\n <div\n ref={ref}\n role=\"listitem\"\n data-component=\"agenda-card\"\n data-component-id={item.id}\n data-status={item.status ?? 'confirmed'}\n className={agendaCardVariants({ size, interactive, className })}\n {...rest}\n >\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-flex ds:flex-col ds:w-12 ds:shrink-0 type-body-sm ds:font-medium ds:text-[color:var(--foreground)] ds:tabular-nums\"\n >\n {item.time}\n {item.dateLabel ? (\n <span className=\"type-eyebrow ds:font-normal ds:text-[color:var(--muted-foreground)]\">\n {item.dateLabel}\n </span>\n ) : null}\n </span>\n\n <Avatar\n name={item.patient.name}\n src={item.patient.avatarUrl}\n size={size === 'md' ? 'md' : 'sm'}\n className=\"ds:shrink-0\"\n aria-hidden=\"true\"\n role=\"presentation\"\n aria-label={undefined}\n />\n\n <div className=\"ds:flex-1 ds:min-w-0 ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n {activator}\n {item.treatment ? (\n <span className=\"type-eyebrow ds:text-[color:var(--muted-foreground)] ds:truncate\">\n {item.treatment}\n </span>\n ) : null}\n {item.meta ? (\n <span className=\"type-eyebrow ds:text-[color:var(--muted-foreground)] ds:truncate\">\n {item.meta}\n </span>\n ) : null}\n {item.note ? (\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)] ds:line-clamp-2\">\n {item.note}\n </span>\n ) : null}\n </div>\n\n {actions ? (\n // Above the stretched-link overlay so the buttons stay clickable.\n <span className=\"ds:relative ds:z-[1] ds:flex ds:items-center ds:gap-[var(--spacing-2xs)] ds:shrink-0\">\n {actions}\n </span>\n ) : null}\n\n {item.status && item.status !== 'confirmed' ? (\n <Badge\n variant={STATUS_TONE[item.status]}\n size=\"sm\"\n withDot\n className=\"ds:shrink-0\"\n >\n {t(`agendaCard.status.${item.status}`, item.status)}\n </Badge>\n ) : null}\n\n {interactive ? (\n <ChevronRight\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:shrink-0 ds:text-[color:var(--muted-foreground)] ds:opacity-0 ds:transition-opacity ds:motion-reduce:transition-none ds:group-hover:opacity-100 ds:group-focus-within:opacity-100 ds:rtl:rotate-180\"\n />\n ) : null}\n </div>\n );\n },\n);\n\nAgendaCard.displayName = 'AgendaCard';\n"],"names":["agendaCardVariants","cva","stretchedLinkClass","STATUS_TONE","AgendaCard","forwardRef","item","size","onActivate","actions","className","rest","ref","t","useTranslation","interactive","hasSafeUrl","isSafeEntityUrl","baseLabel","ariaLabel","titleNode","jsx","activator","e","jsxs","Avatar","Badge","ChevronRight"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import { useTranslation as M } from "react-i18next";
|
|
|
5
5
|
import { I as q } from "./icon-button-LqoiKcUN.js";
|
|
6
6
|
import { S as A } from "./skeleton-CZbwyJAA.js";
|
|
7
7
|
import { E as D } from "./empty-state-BLy7tigq.js";
|
|
8
|
-
import { A as V } from "./agenda-card-
|
|
8
|
+
import { A as V } from "./agenda-card-BxSFkqgY.js";
|
|
9
9
|
import { u as F } from "./registry-nPAVE19X.js";
|
|
10
10
|
import { C as G } from "./calendar-days-C4BmpCZg.js";
|
|
11
11
|
import { P as J } from "./plus-CYKNmfuA.js";
|
|
@@ -200,4 +200,4 @@ export {
|
|
|
200
200
|
U as A,
|
|
201
201
|
L as a
|
|
202
202
|
};
|
|
203
|
-
//# sourceMappingURL=agenda-tray-
|
|
203
|
+
//# sourceMappingURL=agenda-tray-T-BumlGZ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agenda-tray-Bh1KfEOG.js","sources":["../../src/components/agenda-tray/agenda-tray.agent.ts","../../src/components/agenda-tray/agenda-tray.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — AgendaTray. */\n/* */\n/* Tray-level surface: read appointment ids + lifecycle status (never */\n/* patient names / treatments), and route an activation through the */\n/* curated handle. AgendaTray is in-page (no open/close). */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { AgendaTrayHandle } from './agenda-tray';\n\nexport const agendaTrayAgent: AgentAdapter<AgendaTrayHandle> = {\n id: 'agenda-tray',\n capabilities: ['select_single'],\n state: {\n items: {\n type: 'Array<{ id: string; status: string }>',\n descriptionKey: 'ui.agent.agendaTray.state.items',\n description:\n 'Currently-displayed appointments. Ids + status only — never patient identity.',\n read: (handle) => handle.getItems(),\n },\n },\n actions: {\n select_item: {\n safety: 'read',\n argsType: '{ id: string }',\n descriptionKey: 'ui.agent.agendaTray.actions.selectItem',\n description: 'Activate the appointment with the given id.',\n invoke: (handle, args: { id: string }) => {\n handle.selectItem(args.id);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'agenda-tray',\n description: 'Marks the AgendaTray wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific tray from the agent.',\n },\n item: {\n attr: 'data-appointment-id',\n description:\n 'Stable appointment id emitted on each rendered AgendaCard inside the tray.',\n },\n },\n};\n","import {\n forwardRef,\n useImperativeHandle,\n useMemo,\n useRef,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { CalendarDays, Plus } from 'lucide-react';\nimport { IconButton } from '../button/icon-button';\nimport { Skeleton } from '../skeleton/skeleton';\nimport { EmptyState } from '../empty-state/empty-state';\nimport { AgendaCard, type AgendaItem } from '../agenda-card';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { agendaTrayAgent } from './agenda-tray.agent';\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst agendaTrayVariants = cva(\n [\n 'ds:flex ds:flex-col',\n 'ds:rounded-[var(--radius-md)] ds:shadow-[var(--shadow-card)]',\n 'ds:border ds:border-[color:var(--card-border)] ds:[.theme-accessible_&]:border-2',\n 'ds:bg-[color:var(--card)] ds:text-[color:var(--card-foreground)]',\n 'ds:overflow-hidden',\n ].join(' '),\n {\n variants: {\n size: {\n sm: '',\n md: '',\n },\n },\n defaultVariants: {\n size: 'sm',\n },\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\n/**\n * Curated imperative handle for AgendaTray. Exposed as the forwardRef\n * target so a future agent / MCP UI bridge can drive the tray without\n * touching the DOM. See `agenda-tray.agent.ts`.\n */\nexport interface AgendaTrayHandle {\n getItems: () => Array<{ id: string; status: string }>;\n selectItem: (id: string) => void;\n}\n\nexport interface AgendaTrayProps\n extends\n Omit<HTMLAttributes<HTMLElement>, 'onClick' | 'id'>,\n VariantProps<typeof agendaTrayVariants> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so\n * an agent / MCP UI bridge can address this specific tray.\n */\n id?: string;\n items: AgendaItem[];\n /** Section title — rendered in the header. Localised by the consumer. */\n title?: string;\n /** Optional small caption (e.g. localised date) shown next to the title. */\n caption?: string;\n size?: 'sm' | 'md';\n onOpenAppointment?: (item: AgendaItem) => void;\n onAddAppointment?: () => void;\n /** Localised label for the \"Add\" affordance. */\n addLabel?: string;\n loading?: boolean;\n emptyTitle?: string;\n emptyDescription?: string;\n /** Optional CTA wired into the empty state (EmptyState primaryAction). */\n emptyAction?: { label: string; onClick: () => void };\n /**\n * Pinned footer link (e.g. \"All upcoming appointments\"). Localised by\n * the consumer; rendered after the list, before the section closes.\n */\n viewAllLabel?: string;\n /** Fires when the footer link is activated. Required to render it. */\n onViewAll?: () => void;\n /**\n * Per-row trailing action toolbar, forwarded to each AgendaCard's\n * `actions` slot.\n */\n renderItemActions?: (item: AgendaItem) => ReactNode;\n /**\n * Constrain the list to the tray's own height and scroll inside it —\n * pair with a height/max-height on `className`. The scroll region is\n * keyboard-focusable so it stays operable without a pointer.\n */\n scrollable?: boolean;\n}\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const AgendaTray = forwardRef<HTMLElement, AgendaTrayProps>(\n (\n {\n id,\n items,\n title,\n caption,\n size = 'sm',\n onOpenAppointment,\n onAddAppointment,\n addLabel,\n loading = false,\n emptyTitle,\n emptyDescription,\n emptyAction,\n viewAllLabel,\n onViewAll,\n renderItemActions,\n scrollable = false,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const heading = title ?? t('agendaTray.title', \"Today's appointments\");\n const resolvedAddLabel = addLabel ?? t('agendaTray.add', 'Add appointment');\n const isEmpty = !loading && items.length === 0;\n\n let body: ReactNode;\n if (loading) {\n body = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)]\">\n {[0, 1, 2].map((i) => (\n <Skeleton key={i} variant=\"rectangular\" height=\"2.5rem\" />\n ))}\n </div>\n );\n } else if (isEmpty) {\n body = (\n <div className=\"ds:p-[var(--spacing-md)]\">\n <EmptyState\n variant=\"first-use\"\n size=\"sm\"\n title={emptyTitle ?? t('agendaTray.empty.title', 'No appointments')}\n description={\n emptyDescription ??\n t(\n 'agendaTray.empty.description',\n 'New appointments will appear here.',\n )\n }\n primaryAction={emptyAction}\n />\n </div>\n );\n } else {\n body = (\n <ul\n className={[\n // flex-1 unconditionally so a footer pins to the tray's\n // bottom edge in equal-height grid rows.\n 'ds:flex ds:list-none ds:flex-col ds:flex-1 ds:min-h-0',\n // Keyboard-focusable when it scrolls (axe\n // scrollable-region-focusable) — pair with a height on the\n // tray's className.\n scrollable ? 'ds:overflow-y-auto' : '',\n ]\n .filter(Boolean)\n .join(' ')}\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex -- scrollable list must be keyboard focusable (axe scrollable-region-focusable)\n tabIndex={scrollable ? 0 : undefined}\n aria-label={scrollable ? heading : undefined}\n >\n {items.map((item) => (\n <AgendaCard\n key={item.id}\n item={item}\n size={size}\n onActivate={onOpenAppointment}\n actions={renderItemActions?.(item)}\n data-appointment-id={item.id}\n />\n ))}\n </ul>\n );\n }\n\n /* Curated imperative handle for agent integration. See\n * agenda-tray.agent.ts. */\n const itemsRef = useRef<AgendaItem[]>(items);\n itemsRef.current = items;\n\n const innerRef = useRef<HTMLElement>(null);\n useImperativeHandle(ref, () => innerRef.current as HTMLElement, []);\n\n const handle = useMemo<AgendaTrayHandle>(\n () => ({\n getItems: () =>\n itemsRef.current.map((i) => ({\n id: i.id,\n status: i.status ?? 'confirmed',\n })),\n selectItem: (targetId: string) => {\n const found = itemsRef.current.find((i) => i.id === targetId);\n if (found) onOpenAppointment?.(found);\n },\n }),\n [onOpenAppointment],\n );\n\n useAgentRegistration(agendaTrayAgent, handle, id);\n\n return (\n <section\n ref={innerRef}\n aria-label={heading}\n data-component=\"agenda-tray\"\n data-component-id={id}\n className={agendaTrayVariants({ size, className })}\n {...rest}\n >\n <header className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)]\">\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)] ds:min-w-0\">\n <h3 className=\"ds:m-0 ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] type-title-card\">\n <CalendarDays aria-hidden=\"true\" className=\"ds:size-4\" />\n {heading}\n </h3>\n {caption ? (\n <span className=\"type-eyebrow ds:text-[color:var(--muted-foreground)]\">\n {caption}\n </span>\n ) : null}\n </div>\n {onAddAppointment ? (\n <IconButton\n icon={<Plus />}\n intent=\"outline\"\n size=\"sm\"\n aria-label={resolvedAddLabel}\n onClick={onAddAppointment}\n />\n ) : null}\n </header>\n {body}\n {viewAllLabel && onViewAll && !isEmpty && !loading ? (\n <footer className=\"ds:[border-block-start:var(--border-width-sm)_solid_var(--card-border)] ds:p-[var(--spacing-sm)]\">\n <button\n type=\"button\"\n onClick={onViewAll}\n className={[\n 'type-label ds:text-[color:var(--link)] ds:underline ds:underline-offset-2 ds:hover:no-underline',\n 'ds:rounded-[var(--radius-sm)] ds:min-h-[var(--min-target-size)] ds:ps-[var(--spacing-xs)] ds:pe-[var(--spacing-xs)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n ].join(' ')}\n >\n {viewAllLabel}\n </button>\n </footer>\n ) : null}\n </section>\n );\n },\n);\n\nAgendaTray.displayName = 'AgendaTray';\n"],"names":["agendaTrayAgent","handle","args","agendaTrayVariants","cva","AgendaTray","forwardRef","id","items","title","caption","size","onOpenAppointment","onAddAppointment","addLabel","loading","emptyTitle","emptyDescription","emptyAction","viewAllLabel","onViewAll","renderItemActions","scrollable","className","rest","ref","t","useTranslation","heading","resolvedAddLabel","isEmpty","body","jsx","i","Skeleton","EmptyState","item","AgendaCard","itemsRef","useRef","innerRef","useImperativeHandle","useMemo","targetId","found","useAgentRegistration","jsxs","CalendarDays","IconButton","Plus"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"agenda-tray-T-BumlGZ.js","sources":["../../src/components/agenda-tray/agenda-tray.agent.ts","../../src/components/agenda-tray/agenda-tray.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — AgendaTray. */\n/* */\n/* Tray-level surface: read appointment ids + lifecycle status (never */\n/* patient names / treatments), and route an activation through the */\n/* curated handle. AgendaTray is in-page (no open/close). */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { AgendaTrayHandle } from './agenda-tray';\n\nexport const agendaTrayAgent: AgentAdapter<AgendaTrayHandle> = {\n id: 'agenda-tray',\n capabilities: ['select_single'],\n state: {\n items: {\n type: 'Array<{ id: string; status: string }>',\n descriptionKey: 'ui.agent.agendaTray.state.items',\n description:\n 'Currently-displayed appointments. Ids + status only — never patient identity.',\n read: (handle) => handle.getItems(),\n },\n },\n actions: {\n select_item: {\n safety: 'read',\n argsType: '{ id: string }',\n descriptionKey: 'ui.agent.agendaTray.actions.selectItem',\n description: 'Activate the appointment with the given id.',\n invoke: (handle, args: { id: string }) => {\n handle.selectItem(args.id);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'agenda-tray',\n description: 'Marks the AgendaTray wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific tray from the agent.',\n },\n item: {\n attr: 'data-appointment-id',\n description:\n 'Stable appointment id emitted on each rendered AgendaCard inside the tray.',\n },\n },\n};\n","import {\n forwardRef,\n useImperativeHandle,\n useMemo,\n useRef,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { CalendarDays, Plus } from 'lucide-react';\nimport { IconButton } from '../button/icon-button';\nimport { Skeleton } from '../skeleton/skeleton';\nimport { EmptyState } from '../empty-state/empty-state';\nimport { AgendaCard, type AgendaItem } from '../agenda-card';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { agendaTrayAgent } from './agenda-tray.agent';\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst agendaTrayVariants = cva(\n [\n 'ds:flex ds:flex-col',\n 'ds:rounded-[var(--radius-md)] ds:shadow-[var(--shadow-card)]',\n 'ds:border ds:border-[color:var(--card-border)] ds:[.theme-accessible_&]:border-2',\n 'ds:bg-[color:var(--card)] ds:text-[color:var(--card-foreground)]',\n 'ds:overflow-hidden',\n ].join(' '),\n {\n variants: {\n size: {\n sm: '',\n md: '',\n },\n },\n defaultVariants: {\n size: 'sm',\n },\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\n/**\n * Curated imperative handle for AgendaTray. Exposed as the forwardRef\n * target so a future agent / MCP UI bridge can drive the tray without\n * touching the DOM. See `agenda-tray.agent.ts`.\n */\nexport interface AgendaTrayHandle {\n getItems: () => Array<{ id: string; status: string }>;\n selectItem: (id: string) => void;\n}\n\nexport interface AgendaTrayProps\n extends\n Omit<HTMLAttributes<HTMLElement>, 'onClick' | 'id'>,\n VariantProps<typeof agendaTrayVariants> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so\n * an agent / MCP UI bridge can address this specific tray.\n */\n id?: string;\n items: AgendaItem[];\n /** Section title — rendered in the header. Localised by the consumer. */\n title?: string;\n /** Optional small caption (e.g. localised date) shown next to the title. */\n caption?: string;\n size?: 'sm' | 'md';\n onOpenAppointment?: (item: AgendaItem) => void;\n onAddAppointment?: () => void;\n /** Localised label for the \"Add\" affordance. */\n addLabel?: string;\n loading?: boolean;\n emptyTitle?: string;\n emptyDescription?: string;\n /** Optional CTA wired into the empty state (EmptyState primaryAction). */\n emptyAction?: { label: string; onClick: () => void };\n /**\n * Pinned footer link (e.g. \"All upcoming appointments\"). Localised by\n * the consumer; rendered after the list, before the section closes.\n */\n viewAllLabel?: string;\n /** Fires when the footer link is activated. Required to render it. */\n onViewAll?: () => void;\n /**\n * Per-row trailing action toolbar, forwarded to each AgendaCard's\n * `actions` slot.\n */\n renderItemActions?: (item: AgendaItem) => ReactNode;\n /**\n * Constrain the list to the tray's own height and scroll inside it —\n * pair with a height/max-height on `className`. The scroll region is\n * keyboard-focusable so it stays operable without a pointer.\n */\n scrollable?: boolean;\n}\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const AgendaTray = forwardRef<HTMLElement, AgendaTrayProps>(\n (\n {\n id,\n items,\n title,\n caption,\n size = 'sm',\n onOpenAppointment,\n onAddAppointment,\n addLabel,\n loading = false,\n emptyTitle,\n emptyDescription,\n emptyAction,\n viewAllLabel,\n onViewAll,\n renderItemActions,\n scrollable = false,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const heading = title ?? t('agendaTray.title', \"Today's appointments\");\n const resolvedAddLabel = addLabel ?? t('agendaTray.add', 'Add appointment');\n const isEmpty = !loading && items.length === 0;\n\n let body: ReactNode;\n if (loading) {\n body = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)]\">\n {[0, 1, 2].map((i) => (\n <Skeleton key={i} variant=\"rectangular\" height=\"2.5rem\" />\n ))}\n </div>\n );\n } else if (isEmpty) {\n body = (\n <div className=\"ds:p-[var(--spacing-md)]\">\n <EmptyState\n variant=\"first-use\"\n size=\"sm\"\n title={emptyTitle ?? t('agendaTray.empty.title', 'No appointments')}\n description={\n emptyDescription ??\n t(\n 'agendaTray.empty.description',\n 'New appointments will appear here.',\n )\n }\n primaryAction={emptyAction}\n />\n </div>\n );\n } else {\n body = (\n <ul\n className={[\n // flex-1 unconditionally so a footer pins to the tray's\n // bottom edge in equal-height grid rows.\n 'ds:flex ds:list-none ds:flex-col ds:flex-1 ds:min-h-0',\n // Keyboard-focusable when it scrolls (axe\n // scrollable-region-focusable) — pair with a height on the\n // tray's className.\n scrollable ? 'ds:overflow-y-auto' : '',\n ]\n .filter(Boolean)\n .join(' ')}\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex -- scrollable list must be keyboard focusable (axe scrollable-region-focusable)\n tabIndex={scrollable ? 0 : undefined}\n aria-label={scrollable ? heading : undefined}\n >\n {items.map((item) => (\n <AgendaCard\n key={item.id}\n item={item}\n size={size}\n onActivate={onOpenAppointment}\n actions={renderItemActions?.(item)}\n data-appointment-id={item.id}\n />\n ))}\n </ul>\n );\n }\n\n /* Curated imperative handle for agent integration. See\n * agenda-tray.agent.ts. */\n const itemsRef = useRef<AgendaItem[]>(items);\n itemsRef.current = items;\n\n const innerRef = useRef<HTMLElement>(null);\n useImperativeHandle(ref, () => innerRef.current as HTMLElement, []);\n\n const handle = useMemo<AgendaTrayHandle>(\n () => ({\n getItems: () =>\n itemsRef.current.map((i) => ({\n id: i.id,\n status: i.status ?? 'confirmed',\n })),\n selectItem: (targetId: string) => {\n const found = itemsRef.current.find((i) => i.id === targetId);\n if (found) onOpenAppointment?.(found);\n },\n }),\n [onOpenAppointment],\n );\n\n useAgentRegistration(agendaTrayAgent, handle, id);\n\n return (\n <section\n ref={innerRef}\n aria-label={heading}\n data-component=\"agenda-tray\"\n data-component-id={id}\n className={agendaTrayVariants({ size, className })}\n {...rest}\n >\n <header className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)]\">\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)] ds:min-w-0\">\n <h3 className=\"ds:m-0 ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] type-title-card\">\n <CalendarDays aria-hidden=\"true\" className=\"ds:size-4\" />\n {heading}\n </h3>\n {caption ? (\n <span className=\"type-eyebrow ds:text-[color:var(--muted-foreground)]\">\n {caption}\n </span>\n ) : null}\n </div>\n {onAddAppointment ? (\n <IconButton\n icon={<Plus />}\n intent=\"outline\"\n size=\"sm\"\n aria-label={resolvedAddLabel}\n onClick={onAddAppointment}\n />\n ) : null}\n </header>\n {body}\n {viewAllLabel && onViewAll && !isEmpty && !loading ? (\n <footer className=\"ds:[border-block-start:var(--border-width-sm)_solid_var(--card-border)] ds:p-[var(--spacing-sm)]\">\n <button\n type=\"button\"\n onClick={onViewAll}\n className={[\n 'type-label ds:text-[color:var(--link)] ds:underline ds:underline-offset-2 ds:hover:no-underline',\n 'ds:rounded-[var(--radius-sm)] ds:min-h-[var(--min-target-size)] ds:ps-[var(--spacing-xs)] ds:pe-[var(--spacing-xs)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n ].join(' ')}\n >\n {viewAllLabel}\n </button>\n </footer>\n ) : null}\n </section>\n );\n },\n);\n\nAgendaTray.displayName = 'AgendaTray';\n"],"names":["agendaTrayAgent","handle","args","agendaTrayVariants","cva","AgendaTray","forwardRef","id","items","title","caption","size","onOpenAppointment","onAddAppointment","addLabel","loading","emptyTitle","emptyDescription","emptyAction","viewAllLabel","onViewAll","renderItemActions","scrollable","className","rest","ref","t","useTranslation","heading","resolvedAddLabel","isEmpty","body","jsx","i","Skeleton","EmptyState","item","AgendaCard","itemsRef","useRef","innerRef","useImperativeHandle","useMemo","targetId","found","useAgentRegistration","jsxs","CalendarDays","IconButton","Plus"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import { forwardRef as N, useState as k, useRef as q, useMemo as I } from "react
|
|
|
3
3
|
import { c as L } from "./index-D2ZczOXr.js";
|
|
4
4
|
import { useTranslation as R } from "react-i18next";
|
|
5
5
|
import { A as d } from "./alert-_mUKLmwA.js";
|
|
6
|
-
import { B as w } from "./badge-
|
|
6
|
+
import { B as w } from "./badge-CqGsX32l.js";
|
|
7
7
|
import { B as T } from "./button-DD_0Xdmr.js";
|
|
8
8
|
import { C as V } from "./checkbox-DRcOdmXv.js";
|
|
9
9
|
import { S as j } from "./spinner-hbwuKwMf.js";
|
|
@@ -167,4 +167,4 @@ export {
|
|
|
167
167
|
P as A,
|
|
168
168
|
K as a
|
|
169
169
|
};
|
|
170
|
-
//# sourceMappingURL=ai-consent-banner-
|
|
170
|
+
//# sourceMappingURL=ai-consent-banner-Dxtx_WAh.js.map
|
package/dist/_chunks/{ai-consent-banner-Btzmk8OH.js.map → ai-consent-banner-Dxtx_WAh.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-consent-banner-Btzmk8OH.js","sources":["../../src/components/ai-consent-banner/ai-consent-banner.agent.ts","../../src/components/ai-consent-banner/ai-consent-banner.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — AiConsentBanner. */\n/* */\n/* Read-only structural surface: the current consent state and whether */\n/* the grant affordance is armed. Identifiers / structural state ONLY — */\n/* never the grantee's name or any PHI. The real consent gate lives */\n/* server-side; this adapter does not expose a grant action so an agent */\n/* cannot consent on a user's behalf. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { AiConsentBannerHandle } from './ai-consent-banner';\n\nexport const aiConsentBannerAgent: AgentAdapter<AiConsentBannerHandle> = {\n id: 'ai-consent-banner',\n capabilities: [],\n state: {\n consentState: {\n type: \"'granted' | 'required' | 'pending'\",\n descriptionKey: 'ui.agent.aiConsentBanner.state.consentState',\n description:\n 'Current consent state. Structural only — never the grantee identity.',\n read: (handle) => handle.getState(),\n },\n armed: {\n type: 'boolean',\n descriptionKey: 'ui.agent.aiConsentBanner.state.armed',\n description:\n 'Whether the consent confirmation checkbox is ticked (required state only).',\n read: (handle) => handle.isArmed(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'ai-consent-banner',\n description: 'Marks the AiConsentBanner root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific banner from the agent.',\n },\n },\n};\n","import {\n forwardRef,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Alert } from '../alert/alert';\nimport { Badge } from '../badge/badge';\nimport { Button } from '../button/button';\nimport { Checkbox } from '../checkbox/checkbox';\nimport { Spinner } from '../spinner/spinner';\nimport { Timestamp } from '../timestamp/timestamp';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { aiConsentBannerAgent } from './ai-consent-banner.agent';\n\n/* -------------------------------------------------------------------- */\n/* AiConsentBanner */\n/* */\n/* Presentational AI-consent gate surfaced above an AI-assisted surface */\n/* (e.g. Alfascribe consultation transcription). The SERVER owns the */\n/* real gate — this component only reflects the consent record and lets */\n/* the operator initiate a grant; it never enforces access itself. */\n/* */\n/* Three states drive the Alert variant + body: */\n/* - granted → success Alert with a Badge + when/who it was granted. */\n/* - required → info Alert with a Checkbox-gated Grant Button. */\n/* - pending → info Alert in a disabled, Spinner-busy state while the */\n/* server persists the grant. */\n/* */\n/* All visible text flows through useTranslation('ui') against the */\n/* `aiConsentBanner.*` namespace. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* CVA — root */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva('ds:w-full ds:text-[color:var(--foreground)]', {\n variants: {\n state: {\n granted: '',\n required: '',\n pending: '',\n },\n },\n defaultVariants: {\n state: 'required',\n },\n});\n\n/* -------------------------------------------------------------------- */\n/* State derivation */\n/* -------------------------------------------------------------------- */\n\nexport type AiConsentState = NonNullable<\n VariantProps<typeof rootVariants>['state']\n>;\n\n/** Pending wins over granted/required so the busy state is never masked. */\nfunction deriveState(granted: boolean, pending: boolean): AiConsentState {\n if (pending) return 'pending';\n return granted ? 'granted' : 'required';\n}\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\n/** Agent-readiness curated handle. Exposes the structural consent state only. */\nexport interface AiConsentBannerHandle {\n /** Current derived state: 'granted' | 'required' | 'pending'. */\n getState: () => AiConsentState;\n /** Whether the Grant affordance is currently armed (checkbox ticked). */\n isArmed: () => boolean;\n}\n\nexport interface AiConsentBannerProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'aria-label' | 'children' | 'role'\n> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so an\n * agent / MCP UI bridge can address this specific banner. Mirrored to the\n * real DOM `id`.\n */\n id?: string;\n /** Whether consent has already been granted. Server-sourced. */\n granted: boolean;\n /**\n * When consent was granted — ISO-8601 string, ms-epoch, or Date. Rendered\n * via `Timestamp` in the granted state.\n */\n grantedAt?: string | number | Date;\n /** Who granted consent (operator display name / role). Granted state only. */\n grantedBy?: string;\n /**\n * Whether the current user is allowed to grant consent. When `false`, the\n * required-state Grant affordance is hidden and a not-allowed note shows.\n * Default `true`.\n */\n canGrant?: boolean;\n /** The grant is being persisted server-side — shows the busy Spinner state. */\n pending?: boolean;\n /** Fired when the operator confirms the consent grant. */\n onGrantConsent?: () => void;\n /** Override the region's accessible name. */\n 'aria-label'?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const AiConsentBanner = forwardRef<HTMLDivElement, AiConsentBannerProps>(\n (\n {\n id,\n granted,\n grantedAt,\n grantedBy,\n canGrant = true,\n pending = false,\n onGrantConsent,\n 'aria-label': ariaLabel,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const state = deriveState(granted, pending);\n\n // Local arm switch — the required state gates the Grant Button behind an\n // explicit \"I understand\" checkbox so consent is never one mis-click away.\n const [armed, setArmed] = useState(false);\n\n const armedRef = useRef(armed);\n armedRef.current = armed;\n\n const handle = useMemo<AiConsentBannerHandle>(\n () => ({\n getState: () => deriveState(granted, pending),\n isArmed: () => armedRef.current,\n }),\n [granted, pending],\n );\n useAgentRegistration(aiConsentBannerAgent, handle, id);\n\n const resolvedAriaLabel =\n ariaLabel ?? t('aiConsentBanner.regionLabel', 'AI assistance consent');\n\n // Alert variant per state: granted → success, required/pending → info.\n const alertVariant = state === 'granted' ? 'success' : 'info';\n\n let body: React.ReactNode;\n if (state === 'granted') {\n body = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Badge variant=\"success\">\n {t('aiConsentBanner.badge.granted', 'Consent granted')}\n </Badge>\n {grantedAt !== undefined ? (\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.grantedAtPrefix', 'Granted')}{' '}\n <Timestamp value={grantedAt} format=\"relative\" shape=\"inline\" />\n </span>\n ) : null}\n </div>\n {grantedBy ? (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.grantedBy', {\n name: grantedBy,\n defaultValue: 'By {{name}}',\n })}\n </p>\n ) : null}\n </div>\n );\n } else if (state === 'pending') {\n body = (\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Spinner\n variant=\"pulse\"\n size=\"sm\"\n label={t('aiConsentBanner.pendingLabel', 'Saving consent…')}\n />\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.pendingLabel', 'Saving consent…')}\n </span>\n </div>\n );\n } else {\n // required\n body = canGrant ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n <Checkbox\n checked={armed}\n onCheckedChange={(next) => setArmed(next === true)}\n label={t(\n 'aiConsentBanner.confirmLabel',\n 'I confirm consent has been obtained for AI assistance.',\n )}\n />\n <Alert.Action>\n <Button\n intent=\"primary\"\n size=\"sm\"\n disabled={!armed}\n onClick={onGrantConsent}\n >\n {t('aiConsentBanner.grantButton', 'Grant consent')}\n </Button>\n </Alert.Action>\n </div>\n ) : (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {t(\n 'aiConsentBanner.notAllowed',\n 'You do not have permission to grant AI assistance consent.',\n )}\n </p>\n );\n }\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-label={resolvedAriaLabel}\n aria-busy={state === 'pending' ? true : undefined}\n data-component=\"ai-consent-banner\"\n data-component-id={id}\n data-state={state}\n id={id}\n className={rootVariants({ state, className })}\n {...rest}\n >\n <Alert\n variant={alertVariant}\n icon={state === 'pending' ? null : undefined}\n >\n <Alert.Title>\n {t('aiConsentBanner.title', 'AI assistance consent')}\n </Alert.Title>\n <Alert.Description>\n {state === 'granted'\n ? t(\n 'aiConsentBanner.description.granted',\n 'AI assistance is enabled for this record.',\n )\n : t(\n 'aiConsentBanner.description.required',\n 'AI assistance requires recorded consent before it can run.',\n )}\n </Alert.Description>\n {body}\n </Alert>\n </div>\n );\n },\n);\n\nAiConsentBanner.displayName = 'AiConsentBanner';\n"],"names":["aiConsentBannerAgent","handle","rootVariants","cva","deriveState","granted","pending","AiConsentBanner","forwardRef","id","grantedAt","grantedBy","canGrant","onGrantConsent","ariaLabel","className","rest","ref","t","useTranslation","state","armed","setArmed","useState","armedRef","useRef","useMemo","useAgentRegistration","resolvedAriaLabel","alertVariant","body","jsxs","jsx","Badge","Timestamp","Spinner","Checkbox","next","Alert","Button"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ai-consent-banner-Dxtx_WAh.js","sources":["../../src/components/ai-consent-banner/ai-consent-banner.agent.ts","../../src/components/ai-consent-banner/ai-consent-banner.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — AiConsentBanner. */\n/* */\n/* Read-only structural surface: the current consent state and whether */\n/* the grant affordance is armed. Identifiers / structural state ONLY — */\n/* never the grantee's name or any PHI. The real consent gate lives */\n/* server-side; this adapter does not expose a grant action so an agent */\n/* cannot consent on a user's behalf. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { AiConsentBannerHandle } from './ai-consent-banner';\n\nexport const aiConsentBannerAgent: AgentAdapter<AiConsentBannerHandle> = {\n id: 'ai-consent-banner',\n capabilities: [],\n state: {\n consentState: {\n type: \"'granted' | 'required' | 'pending'\",\n descriptionKey: 'ui.agent.aiConsentBanner.state.consentState',\n description:\n 'Current consent state. Structural only — never the grantee identity.',\n read: (handle) => handle.getState(),\n },\n armed: {\n type: 'boolean',\n descriptionKey: 'ui.agent.aiConsentBanner.state.armed',\n description:\n 'Whether the consent confirmation checkbox is ticked (required state only).',\n read: (handle) => handle.isArmed(),\n },\n },\n actions: {},\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'ai-consent-banner',\n description: 'Marks the AiConsentBanner root region.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific banner from the agent.',\n },\n },\n};\n","import {\n forwardRef,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Alert } from '../alert/alert';\nimport { Badge } from '../badge/badge';\nimport { Button } from '../button/button';\nimport { Checkbox } from '../checkbox/checkbox';\nimport { Spinner } from '../spinner/spinner';\nimport { Timestamp } from '../timestamp/timestamp';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { aiConsentBannerAgent } from './ai-consent-banner.agent';\n\n/* -------------------------------------------------------------------- */\n/* AiConsentBanner */\n/* */\n/* Presentational AI-consent gate surfaced above an AI-assisted surface */\n/* (e.g. Alfascribe consultation transcription). The SERVER owns the */\n/* real gate — this component only reflects the consent record and lets */\n/* the operator initiate a grant; it never enforces access itself. */\n/* */\n/* Three states drive the Alert variant + body: */\n/* - granted → success Alert with a Badge + when/who it was granted. */\n/* - required → info Alert with a Checkbox-gated Grant Button. */\n/* - pending → info Alert in a disabled, Spinner-busy state while the */\n/* server persists the grant. */\n/* */\n/* All visible text flows through useTranslation('ui') against the */\n/* `aiConsentBanner.*` namespace. */\n/* -------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------- */\n/* CVA — root */\n/* -------------------------------------------------------------------- */\n\nconst rootVariants = cva('ds:w-full ds:text-[color:var(--foreground)]', {\n variants: {\n state: {\n granted: '',\n required: '',\n pending: '',\n },\n },\n defaultVariants: {\n state: 'required',\n },\n});\n\n/* -------------------------------------------------------------------- */\n/* State derivation */\n/* -------------------------------------------------------------------- */\n\nexport type AiConsentState = NonNullable<\n VariantProps<typeof rootVariants>['state']\n>;\n\n/** Pending wins over granted/required so the busy state is never masked. */\nfunction deriveState(granted: boolean, pending: boolean): AiConsentState {\n if (pending) return 'pending';\n return granted ? 'granted' : 'required';\n}\n\n/* -------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------- */\n\n/** Agent-readiness curated handle. Exposes the structural consent state only. */\nexport interface AiConsentBannerHandle {\n /** Current derived state: 'granted' | 'required' | 'pending'. */\n getState: () => AiConsentState;\n /** Whether the Grant affordance is currently armed (checkbox ticked). */\n isArmed: () => boolean;\n}\n\nexport interface AiConsentBannerProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'aria-label' | 'children' | 'role'\n> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so an\n * agent / MCP UI bridge can address this specific banner. Mirrored to the\n * real DOM `id`.\n */\n id?: string;\n /** Whether consent has already been granted. Server-sourced. */\n granted: boolean;\n /**\n * When consent was granted — ISO-8601 string, ms-epoch, or Date. Rendered\n * via `Timestamp` in the granted state.\n */\n grantedAt?: string | number | Date;\n /** Who granted consent (operator display name / role). Granted state only. */\n grantedBy?: string;\n /**\n * Whether the current user is allowed to grant consent. When `false`, the\n * required-state Grant affordance is hidden and a not-allowed note shows.\n * Default `true`.\n */\n canGrant?: boolean;\n /** The grant is being persisted server-side — shows the busy Spinner state. */\n pending?: boolean;\n /** Fired when the operator confirms the consent grant. */\n onGrantConsent?: () => void;\n /** Override the region's accessible name. */\n 'aria-label'?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const AiConsentBanner = forwardRef<HTMLDivElement, AiConsentBannerProps>(\n (\n {\n id,\n granted,\n grantedAt,\n grantedBy,\n canGrant = true,\n pending = false,\n onGrantConsent,\n 'aria-label': ariaLabel,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const state = deriveState(granted, pending);\n\n // Local arm switch — the required state gates the Grant Button behind an\n // explicit \"I understand\" checkbox so consent is never one mis-click away.\n const [armed, setArmed] = useState(false);\n\n const armedRef = useRef(armed);\n armedRef.current = armed;\n\n const handle = useMemo<AiConsentBannerHandle>(\n () => ({\n getState: () => deriveState(granted, pending),\n isArmed: () => armedRef.current,\n }),\n [granted, pending],\n );\n useAgentRegistration(aiConsentBannerAgent, handle, id);\n\n const resolvedAriaLabel =\n ariaLabel ?? t('aiConsentBanner.regionLabel', 'AI assistance consent');\n\n // Alert variant per state: granted → success, required/pending → info.\n const alertVariant = state === 'granted' ? 'success' : 'info';\n\n let body: React.ReactNode;\n if (state === 'granted') {\n body = (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Badge variant=\"success\">\n {t('aiConsentBanner.badge.granted', 'Consent granted')}\n </Badge>\n {grantedAt !== undefined ? (\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.grantedAtPrefix', 'Granted')}{' '}\n <Timestamp value={grantedAt} format=\"relative\" shape=\"inline\" />\n </span>\n ) : null}\n </div>\n {grantedBy ? (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.grantedBy', {\n name: grantedBy,\n defaultValue: 'By {{name}}',\n })}\n </p>\n ) : null}\n </div>\n );\n } else if (state === 'pending') {\n body = (\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Spinner\n variant=\"pulse\"\n size=\"sm\"\n label={t('aiConsentBanner.pendingLabel', 'Saving consent…')}\n />\n <span className=\"type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {t('aiConsentBanner.pendingLabel', 'Saving consent…')}\n </span>\n </div>\n );\n } else {\n // required\n body = canGrant ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n <Checkbox\n checked={armed}\n onCheckedChange={(next) => setArmed(next === true)}\n label={t(\n 'aiConsentBanner.confirmLabel',\n 'I confirm consent has been obtained for AI assistance.',\n )}\n />\n <Alert.Action>\n <Button\n intent=\"primary\"\n size=\"sm\"\n disabled={!armed}\n onClick={onGrantConsent}\n >\n {t('aiConsentBanner.grantButton', 'Grant consent')}\n </Button>\n </Alert.Action>\n </div>\n ) : (\n <p className=\"type-body-sm ds:m-0 ds:text-[color:var(--muted-foreground)]\">\n {t(\n 'aiConsentBanner.notAllowed',\n 'You do not have permission to grant AI assistance consent.',\n )}\n </p>\n );\n }\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-label={resolvedAriaLabel}\n aria-busy={state === 'pending' ? true : undefined}\n data-component=\"ai-consent-banner\"\n data-component-id={id}\n data-state={state}\n id={id}\n className={rootVariants({ state, className })}\n {...rest}\n >\n <Alert\n variant={alertVariant}\n icon={state === 'pending' ? null : undefined}\n >\n <Alert.Title>\n {t('aiConsentBanner.title', 'AI assistance consent')}\n </Alert.Title>\n <Alert.Description>\n {state === 'granted'\n ? t(\n 'aiConsentBanner.description.granted',\n 'AI assistance is enabled for this record.',\n )\n : t(\n 'aiConsentBanner.description.required',\n 'AI assistance requires recorded consent before it can run.',\n )}\n </Alert.Description>\n {body}\n </Alert>\n </div>\n );\n },\n);\n\nAiConsentBanner.displayName = 'AiConsentBanner';\n"],"names":["aiConsentBannerAgent","handle","rootVariants","cva","deriveState","granted","pending","AiConsentBanner","forwardRef","id","grantedAt","grantedBy","canGrant","onGrantConsent","ariaLabel","className","rest","ref","t","useTranslation","state","armed","setArmed","useState","armedRef","useRef","useMemo","useAgentRegistration","resolvedAriaLabel","alertVariant","body","jsxs","jsx","Badge","Timestamp","Spinner","Checkbox","next","Alert","Button"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { forwardRef as Q, useRef as v, useState as ee, useMemo as
|
|
3
|
-
import { c as
|
|
1
|
+
import { jsxs as I, jsx as p } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as Q, useRef as v, useState as ee, useMemo as z, useCallback as B, useEffect as se, useImperativeHandle as ae } from "react";
|
|
3
|
+
import { c as m } from "./index-D2ZczOXr.js";
|
|
4
4
|
import { useTranslation as ie } from "react-i18next";
|
|
5
5
|
import { I as ne } from "./icon-button-LqoiKcUN.js";
|
|
6
|
-
import { S as te } from "./scroll-area-
|
|
6
|
+
import { S as te } from "./scroll-area-eccd_Uf-.js";
|
|
7
7
|
import { a as oe } from "./tooltip-DvmfrNvB.js";
|
|
8
8
|
import { u as re } from "./use-controllable-state-BiY4xTzM.js";
|
|
9
9
|
import { u as de } from "./use-edge-resize-ZnGG7gyO.js";
|
|
@@ -64,7 +64,7 @@ const ce = {
|
|
|
64
64
|
description: "Stable tool id emitted on each strip IconButton. The active icon also carries data-active set to its id."
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
-
}, ue = "ds:[inline-size:3rem]", fe = "ds:[inline-size:var(--ai-tools-rail-panel-inline-size,22rem)]", F = "--ai-tools-rail-panel-inline-size", pe = 288, ve = 640, be = 352,
|
|
67
|
+
}, ue = "ds:[inline-size:3rem]", fe = "ds:[inline-size:var(--ai-tools-rail-panel-inline-size,22rem)]", F = "--ai-tools-rail-panel-inline-size", pe = 288, ve = 640, be = 352, me = m(
|
|
68
68
|
["ds:flex ds:shrink-0 ds:h-full", "ds:bg-[var(--background)]"].join(" "),
|
|
69
69
|
{
|
|
70
70
|
variants: {
|
|
@@ -73,21 +73,23 @@ const ce = {
|
|
|
73
73
|
// (flex-row, panel rendered first). Shadow faces the main area —
|
|
74
74
|
// no border against main (the rail stays line-free; the only seam
|
|
75
75
|
// is the strip↔panel divider on the open panel, see render).
|
|
76
|
-
|
|
76
|
+
// Accessible (AAA) theme swaps the soft chrome shadow for a solid 1px
|
|
77
|
+
// border on the content-facing edge (border-s for end-docked).
|
|
78
|
+
end: "ds:flex-row ds:shadow-[var(--shadow-chrome-start)] ds:[.theme-accessible_&]:border-s ds:[.theme-accessible_&]:border-[var(--border)] ds:[.theme-accessible_&]:shadow-none",
|
|
77
79
|
// Strip docks inline-start; the panel mounts inline-end of it.
|
|
78
|
-
start: "ds:flex-row-reverse ds:shadow-[var(--shadow-chrome-end)]"
|
|
80
|
+
start: "ds:flex-row-reverse ds:shadow-[var(--shadow-chrome-end)] ds:[.theme-accessible_&]:border-e ds:[.theme-accessible_&]:border-[var(--border)] ds:[.theme-accessible_&]:shadow-none"
|
|
79
81
|
}
|
|
80
82
|
},
|
|
81
83
|
defaultVariants: { side: "end" }
|
|
82
84
|
}
|
|
83
|
-
),
|
|
85
|
+
), ge = m(
|
|
84
86
|
[
|
|
85
87
|
"ds:flex ds:shrink-0 ds:flex-col ds:items-center",
|
|
86
88
|
"ds:pt-[var(--spacing-md)] ds:pb-[var(--spacing-md)]",
|
|
87
89
|
"ds:gap-[var(--spacing-xs)]",
|
|
88
90
|
ue
|
|
89
91
|
].join(" ")
|
|
90
|
-
), he =
|
|
92
|
+
), he = m(
|
|
91
93
|
[
|
|
92
94
|
"ds:relative ds:flex ds:min-h-0 ds:flex-col ds:h-full",
|
|
93
95
|
"ds:bg-[var(--background)]",
|
|
@@ -96,7 +98,7 @@ const ce = {
|
|
|
96
98
|
// consumer adds a transition on the var, suppress it mid-drag.
|
|
97
99
|
"ds:data-[resizing]:transition-none"
|
|
98
100
|
].join(" ")
|
|
99
|
-
), ye =
|
|
101
|
+
), ye = m(
|
|
100
102
|
[
|
|
101
103
|
"ds:absolute ds:[inset-block:0] ds:z-[1] ds:select-none ds:touch-none",
|
|
102
104
|
"ds:[inline-size:var(--resizable-handle-size)] ds:cursor-col-resize",
|
|
@@ -120,7 +122,7 @@ const ce = {
|
|
|
120
122
|
},
|
|
121
123
|
defaultVariants: { edge: "inline-start" }
|
|
122
124
|
}
|
|
123
|
-
), xe =
|
|
125
|
+
), xe = m(
|
|
124
126
|
[
|
|
125
127
|
"ds:absolute ds:-top-[var(--spacing-xs)] ds:-end-[var(--spacing-xs)]",
|
|
126
128
|
"ds:inline-flex ds:items-center ds:justify-center",
|
|
@@ -134,17 +136,17 @@ const ce = {
|
|
|
134
136
|
"ds:forced-colors:outline ds:forced-colors:outline-1 ds:forced-colors:outline-[CanvasText]"
|
|
135
137
|
].join(" ")
|
|
136
138
|
);
|
|
137
|
-
function
|
|
139
|
+
function we(n, s) {
|
|
138
140
|
return n > 99 ? s : String(n);
|
|
139
141
|
}
|
|
140
|
-
const
|
|
142
|
+
const Re = Q(
|
|
141
143
|
({
|
|
142
144
|
id: n,
|
|
143
145
|
tools: s,
|
|
144
146
|
activeToolId: M,
|
|
145
147
|
defaultActiveToolId: U = null,
|
|
146
148
|
onActiveToolChange: W,
|
|
147
|
-
side:
|
|
149
|
+
side: g = "end",
|
|
148
150
|
railLabel: Z,
|
|
149
151
|
resizablePanel: h = !1,
|
|
150
152
|
className: O
|
|
@@ -154,13 +156,13 @@ const Te = Q(
|
|
|
154
156
|
value: M,
|
|
155
157
|
defaultValue: U,
|
|
156
158
|
onChange: W
|
|
157
|
-
}), c = X ?? null,
|
|
159
|
+
}), c = X ?? null, w = v([]), y = v(null), [R, T] = ee(0), f = v(!1), _ = v(!1), u = z(
|
|
158
160
|
() => s.findIndex((e) => e.id === c),
|
|
159
161
|
[s, c]
|
|
160
|
-
), l = u >= 0 ? s[u] : null, Y =
|
|
162
|
+
), l = u >= 0 ? s[u] : null, Y = z(
|
|
161
163
|
() => s.findIndex((e) => !e.disabled),
|
|
162
164
|
[s]
|
|
163
|
-
), x = u >= 0 ? u :
|
|
165
|
+
), x = u >= 0 ? u : R >= 0 && !((P = s[R]) != null && P.disabled) ? R : Y, $ = B(
|
|
164
166
|
(e, a) => {
|
|
165
167
|
const i = s.find((r) => r.id === e);
|
|
166
168
|
!i || i.disabled || (f.current = a, d(c === e ? null : e));
|
|
@@ -177,20 +179,20 @@ const Te = Q(
|
|
|
177
179
|
let t = i, o = 0;
|
|
178
180
|
for (; o < a && ((D = s[t]) != null && D.disabled); )
|
|
179
181
|
t = r ? (t - 1 + a) % a : (t + 1) % a, o += 1;
|
|
180
|
-
(K = s[t]) != null && K.disabled || (e.preventDefault(),
|
|
182
|
+
(K = s[t]) != null && K.disabled || (e.preventDefault(), T(t), (j = w.current[t]) == null || j.focus());
|
|
181
183
|
},
|
|
182
184
|
[s, x]
|
|
183
|
-
),
|
|
185
|
+
), A = v(null);
|
|
184
186
|
se(() => {
|
|
185
|
-
const e =
|
|
187
|
+
const e = A.current;
|
|
186
188
|
if (!e) return;
|
|
187
189
|
const a = (i) => {
|
|
188
190
|
if (i.key !== "Escape" || u < 0) return;
|
|
189
191
|
i.preventDefault();
|
|
190
192
|
const r = u;
|
|
191
|
-
d(null),
|
|
193
|
+
d(null), T(r), requestAnimationFrame(() => {
|
|
192
194
|
var t;
|
|
193
|
-
(t =
|
|
195
|
+
(t = w.current[r]) == null || t.focus();
|
|
194
196
|
});
|
|
195
197
|
};
|
|
196
198
|
return e.addEventListener("keydown", a), () => e.removeEventListener("keydown", a);
|
|
@@ -198,8 +200,8 @@ const Te = Q(
|
|
|
198
200
|
var e;
|
|
199
201
|
l && f.current && ((e = y.current) == null || e.focus()), f.current = !1;
|
|
200
202
|
}, [l]);
|
|
201
|
-
const
|
|
202
|
-
edge:
|
|
203
|
+
const E = g === "end" ? "inline-start" : "inline-end", { separatorProps: N, isResizing: S, isResized: C } = de({
|
|
204
|
+
edge: E,
|
|
203
205
|
targetRef: y,
|
|
204
206
|
cssProperty: F,
|
|
205
207
|
minSize: pe,
|
|
@@ -216,7 +218,7 @@ const Te = Q(
|
|
|
216
218
|
}, [l, h, C, L]);
|
|
217
219
|
const V = v(c);
|
|
218
220
|
V.current = c;
|
|
219
|
-
const
|
|
221
|
+
const k = z(
|
|
220
222
|
() => ({
|
|
221
223
|
getActiveToolId: () => V.current,
|
|
222
224
|
setActiveTool: (e) => {
|
|
@@ -232,20 +234,20 @@ const Te = Q(
|
|
|
232
234
|
}),
|
|
233
235
|
[s, d]
|
|
234
236
|
);
|
|
235
|
-
ae(q, () =>
|
|
237
|
+
ae(q, () => k, [k]), le(ce, k, n);
|
|
236
238
|
const J = b("aiToolsRail.badgeCountOverflow", {
|
|
237
239
|
defaultValue: "99+"
|
|
238
240
|
});
|
|
239
|
-
return /* @__PURE__ */
|
|
241
|
+
return /* @__PURE__ */ I(
|
|
240
242
|
"div",
|
|
241
243
|
{
|
|
242
|
-
ref:
|
|
244
|
+
ref: A,
|
|
243
245
|
"data-component": "ai-tools-rail",
|
|
244
246
|
"data-component-id": n,
|
|
245
|
-
"data-side":
|
|
246
|
-
className: [
|
|
247
|
+
"data-side": g,
|
|
248
|
+
className: [me({ side: g }), O].filter(Boolean).join(" "),
|
|
247
249
|
children: [
|
|
248
|
-
l ? /* @__PURE__ */
|
|
250
|
+
l ? /* @__PURE__ */ I(
|
|
249
251
|
"aside",
|
|
250
252
|
{
|
|
251
253
|
ref: y,
|
|
@@ -259,13 +261,18 @@ const Te = Q(
|
|
|
259
261
|
"data-resizing": S ? "" : void 0,
|
|
260
262
|
className: [
|
|
261
263
|
he(),
|
|
262
|
-
//
|
|
263
|
-
// row).
|
|
264
|
-
//
|
|
265
|
-
//
|
|
266
|
-
//
|
|
267
|
-
//
|
|
268
|
-
|
|
264
|
+
// Subtle shadow — not a line — separating the panel from the
|
|
265
|
+
// icon strip (the tab row). The panel casts a soft chrome
|
|
266
|
+
// shadow toward the strip on its strip-facing edge. `z-[1]`
|
|
267
|
+
// lifts it above the adjacent strip (the panel is already
|
|
268
|
+
// `relative`) so the shadow paints at the seam instead of being
|
|
269
|
+
// covered by the strip's opaque background. Only renders while
|
|
270
|
+
// the panel is open (the aside is unmounted when collapsed), so
|
|
271
|
+
// it never doubles as a rail↔main seam. In the accessible (AAA)
|
|
272
|
+
// theme the soft shadow becomes a solid 1px border on that same
|
|
273
|
+
// strip-facing edge.
|
|
274
|
+
"ds:z-[1]",
|
|
275
|
+
g === "end" ? "ds:shadow-[var(--shadow-chrome-end)] ds:[.theme-accessible_&]:border-e ds:[.theme-accessible_&]:border-[var(--border)] ds:[.theme-accessible_&]:shadow-none" : "ds:shadow-[var(--shadow-chrome-start)] ds:[.theme-accessible_&]:border-s ds:[.theme-accessible_&]:border-[var(--border)] ds:[.theme-accessible_&]:shadow-none",
|
|
269
276
|
"ds:focus-visible:outline-none"
|
|
270
277
|
].join(" "),
|
|
271
278
|
children: [
|
|
@@ -278,7 +285,7 @@ const Te = Q(
|
|
|
278
285
|
defaultValue: "Resize tool panel"
|
|
279
286
|
}),
|
|
280
287
|
"data-resizing": S ? "" : void 0,
|
|
281
|
-
className: ye({ edge:
|
|
288
|
+
className: ye({ edge: E })
|
|
282
289
|
}
|
|
283
290
|
) : null
|
|
284
291
|
]
|
|
@@ -290,7 +297,7 @@ const Te = Q(
|
|
|
290
297
|
role: "toolbar",
|
|
291
298
|
"aria-orientation": "vertical",
|
|
292
299
|
"aria-label": Z ?? b("aiToolsRail.railLabel", { defaultValue: "AI tools" }),
|
|
293
|
-
className:
|
|
300
|
+
className: ge(),
|
|
294
301
|
onKeyDown: G,
|
|
295
302
|
children: s.map((e, a) => {
|
|
296
303
|
const i = e.id === c, r = typeof e.badgeCount == "number" && e.badgeCount > 0, t = r ? b("aiToolsRail.toolWithCount", {
|
|
@@ -298,12 +305,12 @@ const Te = Q(
|
|
|
298
305
|
count: e.badgeCount,
|
|
299
306
|
defaultValue: "{{tool}}, {{count}} updates"
|
|
300
307
|
}) : e.label;
|
|
301
|
-
return /* @__PURE__ */
|
|
308
|
+
return /* @__PURE__ */ I("div", { className: "ds:relative", children: [
|
|
302
309
|
/* @__PURE__ */ p(
|
|
303
310
|
ne,
|
|
304
311
|
{
|
|
305
312
|
ref: (o) => {
|
|
306
|
-
|
|
313
|
+
w.current[a] = o;
|
|
307
314
|
},
|
|
308
315
|
icon: e.icon,
|
|
309
316
|
tooltip: e.label,
|
|
@@ -317,18 +324,18 @@ const Te = Q(
|
|
|
317
324
|
"data-tool-id": e.id,
|
|
318
325
|
tabIndex: a === x ? 0 : -1,
|
|
319
326
|
onFocus: () => {
|
|
320
|
-
e.disabled ||
|
|
327
|
+
e.disabled || T(a);
|
|
321
328
|
},
|
|
322
|
-
onClick: () => $(e.id,
|
|
329
|
+
onClick: () => $(e.id, _.current),
|
|
323
330
|
onKeyDown: (o) => {
|
|
324
|
-
(o.key === "Enter" || o.key === " ") && (
|
|
331
|
+
(o.key === "Enter" || o.key === " ") && (_.current = !0);
|
|
325
332
|
},
|
|
326
333
|
onKeyUp: (o) => {
|
|
327
|
-
(o.key === "Enter" || o.key === " ") && (
|
|
334
|
+
(o.key === "Enter" || o.key === " ") && (_.current = !1);
|
|
328
335
|
}
|
|
329
336
|
}
|
|
330
337
|
),
|
|
331
|
-
r ? /* @__PURE__ */ p("span", { "aria-hidden": "true", className: xe(), children:
|
|
338
|
+
r ? /* @__PURE__ */ p("span", { "aria-hidden": "true", className: xe(), children: we(
|
|
332
339
|
e.badgeCount,
|
|
333
340
|
J
|
|
334
341
|
) }) : null
|
|
@@ -341,9 +348,9 @@ const Te = Q(
|
|
|
341
348
|
);
|
|
342
349
|
}
|
|
343
350
|
);
|
|
344
|
-
|
|
351
|
+
Re.displayName = "AiToolsRail";
|
|
345
352
|
export {
|
|
346
|
-
|
|
353
|
+
Re as A,
|
|
347
354
|
ce as a
|
|
348
355
|
};
|
|
349
|
-
//# sourceMappingURL=ai-tools-rail-
|
|
356
|
+
//# sourceMappingURL=ai-tools-rail-DfmewPUN.js.map
|