themelia-react-ui 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +190 -1
- package/README.md +92 -13
- package/dist/{accordion-BRWh3BM1.js → accordion-BRTcsp8J.js} +8 -8
- package/dist/accordion-BRTcsp8J.js.map +1 -0
- package/dist/{action-menu-Cx3SdfbN.js → action-menu-Drxw_vJk.js} +36 -36
- package/dist/action-menu-Drxw_vJk.js.map +1 -0
- package/dist/affordance-geometry.generated-CL84ZN9A.js +63 -0
- package/dist/affordance-geometry.generated-CL84ZN9A.js.map +1 -0
- package/dist/{ai-artifact-DkOArd3-.js → ai-artifact-DLVdK0Py.js} +151 -155
- package/dist/ai-artifact-DLVdK0Py.js.map +1 -0
- package/dist/{app-shell-BH_bGcE2.js → app-shell-C_fKpljx.js} +11 -10
- package/dist/app-shell-C_fKpljx.js.map +1 -0
- package/dist/{attachment-DsLgNHXt.js → attachment-DbjUWsP0.js} +12 -12
- package/dist/{attachment-DsLgNHXt.js.map → attachment-DbjUWsP0.js.map} +1 -1
- package/dist/auth-CAQcasMV.js +723 -0
- package/dist/auth-CAQcasMV.js.map +1 -0
- package/dist/{avatar-CsnWaYmt.js → avatar-Bu2HhitA.js} +76 -71
- package/dist/avatar-Bu2HhitA.js.map +1 -0
- package/dist/{badge-BZXZT9wd.js → badge-CzId1Wlm.js} +4 -4
- package/dist/{badge-BZXZT9wd.js.map → badge-CzId1Wlm.js.map} +1 -1
- package/dist/base/accordion.js +1 -1
- package/dist/base/action-menu.js +1 -1
- package/dist/base/attachment.js +1 -1
- package/dist/base/avatar.js +1 -1
- package/dist/base/badge.js +1 -1
- package/dist/base/buttons.js +3 -2
- package/dist/base/cards.js +3 -3
- package/dist/base/carousel.js +25 -27
- package/dist/base/carousel.js.map +1 -1
- package/dist/base/cascader.js +150 -148
- package/dist/base/cascader.js.map +1 -1
- package/dist/base/chart.js +1 -1
- package/dist/base/choice-inputs.js +3 -2
- package/dist/base/code-block.js +1 -1
- package/dist/base/combobox.js +1 -1
- package/dist/base/command.js +1 -1
- package/dist/base/copyable.js +1 -1
- package/dist/base/date-pickers.js +3 -3
- package/dist/base/display.js +7 -7
- package/dist/base/feedback.js +4 -3
- package/dist/base/forms-numeric.js +1 -1
- package/dist/base/forms.js +2 -2
- package/dist/base/inline-edit.js +233 -0
- package/dist/base/inline-edit.js.map +1 -0
- package/dist/base/item.js +1 -1
- package/dist/base/media-gallery.js +1 -1
- package/dist/base/navigation.js +6 -6
- package/dist/base/popover-menu.js +1 -1
- package/dist/base/popover.js +1 -1
- package/dist/base/qr-code.js +1 -1
- package/dist/base/repeaters.js +33 -33
- package/dist/base/repeaters.js.map +1 -1
- package/dist/base/sheet.js +1 -1
- package/dist/base/sidebar.js +1 -1
- package/dist/base/signature-pad.js +83 -81
- package/dist/base/signature-pad.js.map +1 -1
- package/dist/base/skeleton.js +1 -1
- package/dist/base/spinner.js +1 -1
- package/dist/base/structure.js +1 -1
- package/dist/base/table.js +1 -1
- package/dist/base/text-inputs.js +2 -2
- package/dist/base/toaster.js +6 -6
- package/dist/base/toaster.js.map +1 -1
- package/dist/base/tree.js +1 -1
- package/dist/base/upload-queue.js +1 -1
- package/dist/base/upload.js +3 -3
- package/dist/base/value-inputs.js +1 -1
- package/dist/blocks/admin.js +134 -134
- package/dist/blocks/admin.js.map +1 -1
- package/dist/blocks/ai.js +120 -117
- package/dist/blocks/ai.js.map +1 -1
- package/dist/blocks/analytics/usage-card.js +3 -0
- package/dist/blocks/analytics.js +530 -491
- package/dist/blocks/analytics.js.map +1 -1
- package/dist/blocks/collaboration.js +2 -2
- package/dist/blocks/commerce/receipt.js +1 -1
- package/dist/blocks/commerce.js +395 -383
- package/dist/blocks/commerce.js.map +1 -1
- package/dist/blocks/data-display.js +1 -1
- package/dist/blocks/onboarding.js +6 -6
- package/dist/blocks/onboarding.js.map +1 -1
- package/dist/blocks/planning.js +311 -0
- package/dist/blocks/planning.js.map +1 -0
- package/dist/blocks/timelines.js +1 -1
- package/dist/{breadcrumbs-DdQ_I5ra.js → breadcrumbs-BuYz5SDU.js} +9 -8
- package/dist/breadcrumbs-BuYz5SDU.js.map +1 -0
- package/dist/button-BZDasD04.js +651 -0
- package/dist/button-BZDasD04.js.map +1 -0
- package/dist/{button-BS6l5JUw.js → button-BZyfTvwm.js} +3 -3
- package/dist/button-BZyfTvwm.js.map +1 -0
- package/dist/buttons-D_6KJvEE.js +99 -0
- package/dist/buttons-D_6KJvEE.js.map +1 -0
- package/dist/{cards-BMB0laLG.js → cards-qGSErLw_.js} +12 -12
- package/dist/{cards-BMB0laLG.js.map → cards-qGSErLw_.js.map} +1 -1
- package/dist/chart-Bsc5BICK.js +150 -0
- package/dist/chart-Bsc5BICK.js.map +1 -0
- package/dist/checkbox-BQNDjUCh.js +34 -0
- package/dist/checkbox-BQNDjUCh.js.map +1 -0
- package/dist/choice-inputs-Mk3iWbhr.js +725 -0
- package/dist/choice-inputs-Mk3iWbhr.js.map +1 -0
- package/dist/{code-block-DIlqzoiD.js → code-block-DzHKRybS.js} +23 -23
- package/dist/code-block-DzHKRybS.js.map +1 -0
- package/dist/{collapsible-DsnktFNv.js → collapsible-ClvC7Bj3.js} +3 -3
- package/dist/{collapsible-DsnktFNv.js.map → collapsible-ClvC7Bj3.js.map} +1 -1
- package/dist/{collection-content-C4fthJV_.js → collection-content-D6S8cv_n.js} +3 -3
- package/dist/{collection-content-C4fthJV_.js.map → collection-content-D6S8cv_n.js.map} +1 -1
- package/dist/{combobox-HDftpzxt.js → combobox-BFnbJJp3.js} +18 -18
- package/dist/combobox-BFnbJJp3.js.map +1 -0
- package/dist/{combobox-CHD750do.js → combobox-hozNwUcc.js} +313 -316
- package/dist/combobox-hozNwUcc.js.map +1 -0
- package/dist/{command-D0kWBZfd.js → command-BnmSchli.js} +9 -9
- package/dist/command-BnmSchli.js.map +1 -0
- package/dist/comments-u5L0OGip.js +1156 -0
- package/dist/comments-u5L0OGip.js.map +1 -0
- package/dist/components/base/buttons/button-group.recipes.d.ts +1 -1
- package/dist/components/base/buttons/button.recipes.d.ts +10 -19
- package/dist/components/base/buttons/use-pending-button-focus.d.ts +3 -0
- package/dist/components/base/cards/card.recipes.d.ts +13 -5
- package/dist/components/base/cards/partials/card-primitives.d.ts +9 -4
- package/dist/components/base/cards/smart-card.types.d.ts +3 -1
- package/dist/components/base/date-pickers/date-picker.recipes.d.ts +5 -18
- package/dist/components/base/date-pickers/datepicker.types.d.ts +3 -0
- package/dist/components/base/forms/form-field.d.ts +1 -0
- package/dist/components/base/forms/form-sizing.d.ts +3 -3
- package/dist/components/base/inline-edit/index.d.ts +2 -0
- package/dist/components/base/inline-edit/inline-edit.d.ts +81 -0
- package/dist/components/base/inline-edit/inline-edit.recipes.d.ts +6 -0
- package/dist/components/base/navigation/tabs.d.ts +3 -5
- package/dist/components/base/popover/popover.recipes.d.ts +3 -3
- package/dist/components/base/structure/structure.recipes.d.ts +6 -0
- package/dist/components/base/table/index.d.ts +1 -1
- package/dist/components/base/text-inputs/clear-native-field.d.ts +2 -0
- package/dist/components/base/text-inputs/input-trailing-action.d.ts +3 -0
- package/dist/components/blocks/analytics/index.d.ts +1 -0
- package/dist/components/blocks/analytics/types.d.ts +1 -1
- package/dist/components/blocks/analytics/usage-card/index.d.ts +3 -0
- package/dist/components/blocks/analytics/usage-card/types.d.ts +52 -0
- package/dist/components/blocks/analytics/usage-card/usage-card.d.ts +6 -0
- package/dist/components/blocks/analytics/usage-card/usage-card.data.d.ts +19 -0
- package/dist/components/blocks/analytics/usage-card/usage-card.strings.d.ts +22 -0
- package/dist/components/blocks/collaboration/message/message.recipes.d.ts +12 -0
- package/dist/components/blocks/data-display/empty-state/partials/illustrations/document-stack.d.ts +1 -4
- package/dist/components/blocks/data-display/empty-state/partials/illustrations/inbox-clean.d.ts +1 -4
- package/dist/components/blocks/data-display/empty-state/partials/illustrations/index.d.ts +3 -3
- package/dist/components/blocks/data-display/empty-state/partials/illustrations/stacked-cards.d.ts +1 -6
- package/dist/components/blocks/planning/index.d.ts +3 -0
- package/dist/components/blocks/planning/task-card.d.ts +3 -0
- package/dist/components/blocks/planning/task-card.strings.d.ts +15 -0
- package/dist/components/blocks/planning/task-card.types.d.ts +66 -0
- package/dist/components/features/combobox/components/error-message.d.ts +1 -1
- package/dist/components/features/comments/hooks/use-attachment-upload.d.ts +5 -0
- package/dist/components/features/filters/facets/search-facet.d.ts +0 -12
- package/dist/components/features/filters/facets/tags-facet.d.ts +1 -1
- package/dist/components/features/media-library/media-library.d.ts +1 -1
- package/dist/components/features/media-library/media-library.types.d.ts +9 -1
- package/dist/components/features/media-library/partials/media-library-partials.d.ts +1 -1
- package/dist/components/features/overlays/hooks/use-pending-overlay-focus.d.ts +2 -0
- package/dist/components/features/overlays/overlays.types.d.ts +5 -4
- package/dist/components/features/rich-text-editor/rich-text-editor.recipes.d.ts +2 -1
- package/dist/components/features/table/data-table.d.ts +1 -1
- package/dist/components/features/table/table.types.d.ts +1 -1
- package/dist/components/features/theme-tweaker/theme-provider-settings.d.ts +3 -1
- package/dist/components/layout/auth/auth.types.d.ts +1 -0
- package/dist/components/layout/page/page.d.ts +0 -1
- package/dist/components/layout/page/page.types.d.ts +9 -3
- package/dist/components/layout/sidebar/sidebar.context.d.ts +1 -1
- package/dist/components/layout/sidebar/sidebar.types.d.ts +4 -0
- package/dist/components/layout/workspace/workspace.types.d.ts +3 -0
- package/dist/components/typography/heading.d.ts +5 -2
- package/dist/components/typography/index.d.ts +1 -1
- package/dist/components/typography/text.styles.d.ts +10 -0
- package/dist/components/ui/popover.d.ts +1 -1
- package/dist/components/ui/sidebar.d.ts +1 -1
- package/dist/components/ui/table.d.ts +2 -1
- package/dist/container.recipes-D9t8MHR3.js +27 -0
- package/dist/container.recipes-D9t8MHR3.js.map +1 -0
- package/dist/{containers-CPNyNo1_.js → containers-DqB-bSYE.js} +34 -56
- package/dist/containers-DqB-bSYE.js.map +1 -0
- package/dist/control-group-recipes-DBXmfh2E.js +21 -0
- package/dist/control-group-recipes-DBXmfh2E.js.map +1 -0
- package/dist/{copyable-B7SBXJMr.js → copyable-BTSByfmq.js} +6 -6
- package/dist/{copyable-B7SBXJMr.js.map → copyable-BTSByfmq.js.map} +1 -1
- package/dist/{data-display-b3d1TfL4.js → data-display-Bihs9Ven.js} +542 -329
- package/dist/data-display-Bihs9Ven.js.map +1 -0
- package/dist/{date-BFNMnrS5.js → date-DOKhJPu7.js} +4 -4
- package/dist/{date-BFNMnrS5.js.map → date-DOKhJPu7.js.map} +1 -1
- package/dist/{date-picker-DI6kPNof.js → date-picker-DzP5HQq7.js} +492 -472
- package/dist/date-picker-DzP5HQq7.js.map +1 -0
- package/dist/date-pickers-BpgGz7S-.js +196 -0
- package/dist/date-pickers-BpgGz7S-.js.map +1 -0
- package/dist/{display-ByI5tkqy.js → display-CS6Hbk18.js} +8 -8
- package/dist/{display-ByI5tkqy.js.map → display-CS6Hbk18.js.map} +1 -1
- package/dist/{dropdown-menu-BlnyHr-9.js → dropdown-menu-D-boNgGO.js} +7 -7
- package/dist/{dropdown-menu-BlnyHr-9.js.map → dropdown-menu-D-boNgGO.js.map} +1 -1
- package/dist/features/activities.js +152 -141
- package/dist/features/activities.js.map +1 -1
- package/dist/features/ai-chat.js +182 -179
- package/dist/features/ai-chat.js.map +1 -1
- package/dist/features/async-preview.js +9 -9
- package/dist/features/async-preview.js.map +1 -1
- package/dist/features/combobox.js +1 -1
- package/dist/features/comments.js +1 -1
- package/dist/features/data-view.js +25 -23
- package/dist/features/data-view.js.map +1 -1
- package/dist/features/email-composer/engine.js +1 -1
- package/dist/features/email-composer.js +103 -104
- package/dist/features/email-composer.js.map +1 -1
- package/dist/features/event-calendar.js +375 -373
- package/dist/features/event-calendar.js.map +1 -1
- package/dist/features/filters.js +1 -1
- package/dist/features/global-search.js +222 -224
- package/dist/features/global-search.js.map +1 -1
- package/dist/features/kanban.js +29 -29
- package/dist/features/kanban.js.map +1 -1
- package/dist/features/map.js +59 -58
- package/dist/features/map.js.map +1 -1
- package/dist/features/media-library.js +856 -855
- package/dist/features/media-library.js.map +1 -1
- package/dist/features/mentions.js +1 -1
- package/dist/features/overlays.js +1 -1
- package/dist/features/products.js +1210 -1209
- package/dist/features/products.js.map +1 -1
- package/dist/features/questionnaire.js +133 -132
- package/dist/features/questionnaire.js.map +1 -1
- package/dist/features/resource-assignment.js +29 -31
- package/dist/features/resource-assignment.js.map +1 -1
- package/dist/features/resource.js +13 -13
- package/dist/features/resource.js.map +1 -1
- package/dist/features/rich-text-editor.js +2 -2
- package/dist/features/schema-form.js +82 -82
- package/dist/features/schema-form.js.map +1 -1
- package/dist/features/suggestions.js +3 -3
- package/dist/features/sync.js +4 -4
- package/dist/features/sync.js.map +1 -1
- package/dist/features/table.js +1 -1
- package/dist/features/theme-tweaker.js +456 -450
- package/dist/features/theme-tweaker.js.map +1 -1
- package/dist/feedback-CJkUAapr.js +233 -0
- package/dist/feedback-CJkUAapr.js.map +1 -0
- package/dist/field-affordance-recipes-uKY4MsZ_.js +25 -0
- package/dist/field-affordance-recipes-uKY4MsZ_.js.map +1 -0
- package/dist/{field-state-recipes-CBTRt9Bt.js → field-state-recipes-DQQpiLWC.js} +3 -3
- package/dist/field-state-recipes-DQQpiLWC.js.map +1 -0
- package/dist/{filters-qtrcv1hf.js → filters-D6FF8L6s.js} +715 -720
- package/dist/filters-D6FF8L6s.js.map +1 -0
- package/dist/{form-field-C6W-y2hR.js → form-field-CZwrkP7m.js} +17 -9
- package/dist/form-field-CZwrkP7m.js.map +1 -0
- package/dist/{form-sizing-39NohSqn.js → form-sizing-QP8aIRaW.js} +10 -6
- package/dist/form-sizing-QP8aIRaW.js.map +1 -0
- package/dist/{forms-BF-HSbff.js → forms-B5NCbkSC.js} +35 -35
- package/dist/{forms-BF-HSbff.js.map → forms-B5NCbkSC.js.map} +1 -1
- package/dist/forms-numeric-Crrm80Lm.js +867 -0
- package/dist/forms-numeric-Crrm80Lm.js.map +1 -0
- package/dist/{header-B8ex54cY.js → header-kxruN3RM.js} +53 -49
- package/dist/header-kxruN3RM.js.map +1 -0
- package/dist/{hooks-D6UBVzf2.js → hooks-BrlnCwQd.js} +2 -2
- package/dist/{hooks-D6UBVzf2.js.map → hooks-BrlnCwQd.js.map} +1 -1
- package/dist/{http-CLTVJc5I.js → http-CdEIHyQf.js} +2 -2
- package/dist/http-CdEIHyQf.js.map +1 -0
- package/dist/{icon-badge-Dv0RYQwj.js → icon-badge-Btc6pQrp.js} +4 -4
- package/dist/{icon-badge-Dv0RYQwj.js.map → icon-badge-Btc6pQrp.js.map} +1 -1
- package/dist/index.js +2 -2
- package/dist/input-SX9V0AL3.js +255 -0
- package/dist/input-SX9V0AL3.js.map +1 -0
- package/dist/input-vxcaNCYC.js +20 -0
- package/dist/input-vxcaNCYC.js.map +1 -0
- package/dist/{item-pJ0GsOiJ.js → item-DE4YnuJx.js} +18 -17
- package/dist/item-DE4YnuJx.js.map +1 -0
- package/dist/layout/app-shell.js +1 -1
- package/dist/layout/auth.js +1 -1
- package/dist/layout/containers.js +1 -1
- package/dist/layout/header.js +1 -1
- package/dist/layout/hooks.js +1 -1
- package/dist/layout/navigation.js +1 -1
- package/dist/layout/page.js +1 -1
- package/dist/layout/settings.js +1 -1
- package/dist/layout/sidebar.js +2 -2
- package/dist/layout/workspace.js +1 -1
- package/dist/layout.js +10 -10
- package/dist/lib/affordance-geometry.generated.d.ts +44 -4
- package/dist/lib/control-group-recipes.d.ts +22 -0
- package/dist/lib/field-affordance-recipes.d.ts +35 -2
- package/dist/lib/field-state-recipes.d.ts +2 -2
- package/dist/lib/navigation-row-recipes.d.ts +3 -2
- package/dist/lib/overlay-anatomy-recipes.d.ts +1 -1
- package/dist/lib/surface-recipes.d.ts +5 -2
- package/dist/lib/token-merge.generated.d.ts +144 -2
- package/dist/lib/ui-provider/types.d.ts +4 -2
- package/dist/lib/use-prefers-reduced-motion.d.ts +2 -0
- package/dist/lib/utils.js +1 -1
- package/dist/{media-gallery-Ca4YmvBi.js → media-gallery-DLp3HAz0.js} +75 -74
- package/dist/media-gallery-DLp3HAz0.js.map +1 -0
- package/dist/{mentions-CRio8mTm.js → mentions-Cl0Kt_Pd.js} +52 -50
- package/dist/{mentions-CRio8mTm.js.map → mentions-Cl0Kt_Pd.js.map} +1 -1
- package/dist/message-SZUNB1eX.js +127 -0
- package/dist/message-SZUNB1eX.js.map +1 -0
- package/dist/{navigation-BTrEb5u4.js → navigation-DnQSNMT0.js} +64 -55
- package/dist/navigation-DnQSNMT0.js.map +1 -0
- package/dist/{navigation-DqEITuD2.js → navigation-DyytsLRB.js} +37 -37
- package/dist/navigation-DyytsLRB.js.map +1 -0
- package/dist/{navigation-row-recipes-BFpvGPGE.js → navigation-row-recipes-DQEXQcqY.js} +3 -3
- package/dist/navigation-row-recipes-DQEXQcqY.js.map +1 -0
- package/dist/{number-BNT_BIzJ.js → number-DasMFWEG.js} +4 -4
- package/dist/{number-BNT_BIzJ.js.map → number-DasMFWEG.js.map} +1 -1
- package/dist/overlays-DUbs1KEi.js +1011 -0
- package/dist/overlays-DUbs1KEi.js.map +1 -0
- package/dist/{page-BMBGjJY8.js → page-hGmT4nWK.js} +75 -64
- package/dist/page-hGmT4nWK.js.map +1 -0
- package/dist/{page-header-BH41wCyY.js → page-header-D8nERkn5.js} +9 -9
- package/dist/page-header-D8nERkn5.js.map +1 -0
- package/dist/{pagination-C29vvt3I.js → pagination-NLGqRirf.js} +20 -20
- package/dist/pagination-NLGqRirf.js.map +1 -0
- package/dist/{popover-TInGXsjg.js → popover-CghIYdQf.js} +23 -22
- package/dist/popover-CghIYdQf.js.map +1 -0
- package/dist/{popover-menu-BzqXqE72.js → popover-menu-B4PoWhRl.js} +6 -6
- package/dist/{popover-menu-BzqXqE72.js.map → popover-menu-B4PoWhRl.js.map} +1 -1
- package/dist/{popover.recipes-zgBhMlUu.js → popover.recipes-QlD4JenO.js} +5 -5
- package/dist/popover.recipes-QlD4JenO.js.map +1 -0
- package/dist/{primitives-DKPOGVpj.js → primitives-C7ff0QaI.js} +120 -113
- package/dist/primitives-C7ff0QaI.js.map +1 -0
- package/dist/primitives.js +3 -3
- package/dist/progress-BroqrAyV.js +169 -0
- package/dist/progress-BroqrAyV.js.map +1 -0
- package/dist/{receipt-DYWTQGEc.js → receipt-BuJynLgf.js} +8 -8
- package/dist/{receipt-DYWTQGEc.js.map → receipt-BuJynLgf.js.map} +1 -1
- package/dist/{rich-text-B7sBAdDG.js → rich-text-DlxDOtf4.js} +4 -4
- package/dist/{rich-text-B7sBAdDG.js.map → rich-text-DlxDOtf4.js.map} +1 -1
- package/dist/rich-text-editor-BKyG7rWz.js +574 -0
- package/dist/rich-text-editor-BKyG7rWz.js.map +1 -0
- package/dist/{rich-text-editor.recipes-DxvOE0Lp.js → rich-text-editor.recipes-B72Nfuze.js} +35 -26
- package/dist/rich-text-editor.recipes-B72Nfuze.js.map +1 -0
- package/dist/{scroll-area-BheMQ270.js → scroll-area-D-pIhEKl.js} +3 -3
- package/dist/scroll-area-D-pIhEKl.js.map +1 -0
- package/dist/{separator-Gk_WXH-l.js → separator-BNIgG3au.js} +3 -3
- package/dist/{separator-Gk_WXH-l.js.map → separator-BNIgG3au.js.map} +1 -1
- package/dist/{separator-DO0EbCEm.js → separator-BhtFyo4x.js} +2 -2
- package/dist/{separator-DO0EbCEm.js.map → separator-BhtFyo4x.js.map} +1 -1
- package/dist/services/actions.js +1 -1
- package/dist/{settings-D9f_wdIC.js → settings-DOTOzeZ2.js} +10 -9
- package/dist/{settings-D9f_wdIC.js.map → settings-DOTOzeZ2.js.map} +1 -1
- package/dist/{sheet-vOUloJ4O.js → sheet-BFhrNehm.js} +11 -11
- package/dist/sheet-BFhrNehm.js.map +1 -0
- package/dist/{sidebar-CNBKFDRW.js → sidebar-CyR4XKwR.js} +219 -200
- package/dist/sidebar-CyR4XKwR.js.map +1 -0
- package/dist/{sidebar-C3UKkbC5.js → sidebar-SvGJ0Zwi.js} +63 -58
- package/dist/sidebar-SvGJ0Zwi.js.map +1 -0
- package/dist/{skeleton-BvRhK8y-.js → skeleton-3F0uhYn3.js} +4 -4
- package/dist/{skeleton-BvRhK8y-.js.map → skeleton-3F0uhYn3.js.map} +1 -1
- package/dist/{smart-card-B5FcKODh.js → smart-card-DjGVV2xr.js} +206 -199
- package/dist/smart-card-DjGVV2xr.js.map +1 -0
- package/dist/{spinner-JtlFJ7Nc.js → spinner-Cpf7oRkF.js} +5 -5
- package/dist/{spinner-JtlFJ7Nc.js.map → spinner-Cpf7oRkF.js.map} +1 -1
- package/dist/{structure-BvW4vG4H.js → structure-CRdqVawd.js} +14 -14
- package/dist/{structure-BvW4vG4H.js.map → structure-CRdqVawd.js.map} +1 -1
- package/dist/{structure.recipes-DjqnBpwz.js → structure.recipes-Bqhf9oIh.js} +2 -2
- package/dist/structure.recipes-Bqhf9oIh.js.map +1 -0
- package/dist/style.css +1 -1
- package/dist/{surface-recipes-CQfRr-VL.js → surface-recipes-Dd__PD-w.js} +4 -3
- package/dist/surface-recipes-Dd__PD-w.js.map +1 -0
- package/dist/{table-DnlAJ-xR.js → table-CLtJTxoR.js} +17 -16
- package/dist/table-CLtJTxoR.js.map +1 -0
- package/dist/table-CcRDZiLP.js +1444 -0
- package/dist/table-CcRDZiLP.js.map +1 -0
- package/dist/tabs-BNgu7g0u.js +188 -0
- package/dist/tabs-BNgu7g0u.js.map +1 -0
- package/dist/text-inputs-DsR56TR-.js +330 -0
- package/dist/text-inputs-DsR56TR-.js.map +1 -0
- package/dist/{text.styles-BwB7vAF2.js → text.styles-Q4sGAIgA.js} +18 -10
- package/dist/text.styles-Q4sGAIgA.js.map +1 -0
- package/dist/theme.css +77 -115
- package/dist/{timelines-CnZ2S_Gr.js → timelines-D1pkt3se.js} +84 -78
- package/dist/timelines-D1pkt3se.js.map +1 -0
- package/dist/{tree-COD9BGdU.js → tree-BtmYyMZV.js} +8 -8
- package/dist/{tree-COD9BGdU.js.map → tree-BtmYyMZV.js.map} +1 -1
- package/dist/typography/rich-text.js +1 -1
- package/dist/typography-BxQgiZyw.js +96 -0
- package/dist/typography-BxQgiZyw.js.map +1 -0
- package/dist/typography.js +1 -1
- package/dist/{ui-provider-CftIB6TY.js → ui-provider-DRPn3qNl.js} +3 -2
- package/dist/ui-provider-DRPn3qNl.js.map +1 -0
- package/dist/ui-provider.js +1 -1
- package/dist/{upload-DIzw1dx1.js → upload-CDbYw1WN.js} +326 -323
- package/dist/upload-CDbYw1WN.js.map +1 -0
- package/dist/{upload-queue-xRJ3qDmd.js → upload-queue-CNd_hH_a.js} +25 -25
- package/dist/upload-queue-CNd_hH_a.js.map +1 -0
- package/dist/usage-card-VyJLUwRr.js +457 -0
- package/dist/usage-card-VyJLUwRr.js.map +1 -0
- package/dist/utils-BvH9PSmq.js +4275 -0
- package/dist/utils-BvH9PSmq.js.map +1 -0
- package/dist/value-inputs-D0KCrfVC.js +840 -0
- package/dist/value-inputs-D0KCrfVC.js.map +1 -0
- package/dist/{workspace-Cbqz4FzN.js → workspace-CcR8r-Nt.js} +115 -122
- package/dist/workspace-CcR8r-Nt.js.map +1 -0
- package/docs/consumer-skill/SKILL.md +112 -18
- package/docs/consumer-skill/examples/analytics.tsx +34 -0
- package/docs/consumer-skill/examples/app-layout.tsx +42 -12
- package/docs/consumer-skill/examples/detail.tsx +24 -9
- package/docs/consumer-skill/examples/manifest.json +27 -1
- package/docs/consumer-skill/examples/planning-usage-edit.tsx +29 -0
- package/docs/consumer-skill/examples/scoped-directory.tsx +77 -0
- package/docs/consumer-skill/examples/website.tsx +56 -0
- package/docs/consumer-skill/references/analytics.md +70 -0
- package/docs/consumer-skill/references/composition.md +219 -2
- package/docs/consumer-skill/references/design-contract.md +37 -10
- package/docs/consumer-skill/references/discovery.md +93 -5
- package/docs/consumer-skill/references/installation.md +20 -3
- package/docs/consumer-skill/references/integration.md +26 -0
- package/docs/consumer-skill/references/public-api.json +2416 -388
- package/docs/consumer-skill/references/review.md +126 -0
- package/docs/consumer-skill/references/theming.md +52 -7
- package/docs/consumer-skill/references/tokens.json +177 -9
- package/docs/consumer-skill/references/workflows.md +129 -1
- package/docs/consumer-skill/scripts/check-composition.mjs +31 -0
- package/docs/consumer-skill/scripts/composition-policy.mjs +317 -0
- package/docs/consumer-skill/scripts/discovery.mjs +65 -8
- package/docs/consumer-skill/scripts/surface-policy.mjs +66 -0
- package/package.json +30 -6
- package/dist/accordion-BRWh3BM1.js.map +0 -1
- package/dist/action-menu-Cx3SdfbN.js.map +0 -1
- package/dist/affordance-geometry.generated-DXl-Zb3Z.js +0 -23
- package/dist/affordance-geometry.generated-DXl-Zb3Z.js.map +0 -1
- package/dist/ai-artifact-DkOArd3-.js.map +0 -1
- package/dist/app-shell-BH_bGcE2.js.map +0 -1
- package/dist/auth-BDB1V_2q.js +0 -704
- package/dist/auth-BDB1V_2q.js.map +0 -1
- package/dist/avatar-CsnWaYmt.js.map +0 -1
- package/dist/breadcrumbs-DdQ_I5ra.js.map +0 -1
- package/dist/button-BS6l5JUw.js.map +0 -1
- package/dist/buttons-Co6GavvM.js +0 -674
- package/dist/buttons-Co6GavvM.js.map +0 -1
- package/dist/chart-DVfcwQu6.js +0 -149
- package/dist/chart-DVfcwQu6.js.map +0 -1
- package/dist/choice-inputs-CavA-SGV.js +0 -644
- package/dist/choice-inputs-CavA-SGV.js.map +0 -1
- package/dist/code-block-DIlqzoiD.js.map +0 -1
- package/dist/combobox-CHD750do.js.map +0 -1
- package/dist/combobox-HDftpzxt.js.map +0 -1
- package/dist/command-D0kWBZfd.js.map +0 -1
- package/dist/comments-CvYeglMS.js +0 -1132
- package/dist/comments-CvYeglMS.js.map +0 -1
- package/dist/containers-CPNyNo1_.js.map +0 -1
- package/dist/data-display-b3d1TfL4.js.map +0 -1
- package/dist/date-picker-DI6kPNof.js.map +0 -1
- package/dist/date-pickers-ByP6Cv2z.js +0 -224
- package/dist/date-pickers-ByP6Cv2z.js.map +0 -1
- package/dist/feedback-a9j9J-9A.js +0 -391
- package/dist/feedback-a9j9J-9A.js.map +0 -1
- package/dist/field-affordance-recipes-CHdUtn2Z.js +0 -17
- package/dist/field-affordance-recipes-CHdUtn2Z.js.map +0 -1
- package/dist/field-state-recipes-CBTRt9Bt.js.map +0 -1
- package/dist/filters-qtrcv1hf.js.map +0 -1
- package/dist/form-field-C6W-y2hR.js.map +0 -1
- package/dist/form-sizing-39NohSqn.js.map +0 -1
- package/dist/forms-numeric-Y15Bg5Nr.js +0 -867
- package/dist/forms-numeric-Y15Bg5Nr.js.map +0 -1
- package/dist/header-B8ex54cY.js.map +0 -1
- package/dist/http-CLTVJc5I.js.map +0 -1
- package/dist/input-DMorJiTI.js +0 -202
- package/dist/input-DMorJiTI.js.map +0 -1
- package/dist/input-ci9fIgFH.js +0 -20
- package/dist/input-ci9fIgFH.js.map +0 -1
- package/dist/item-pJ0GsOiJ.js.map +0 -1
- package/dist/media-gallery-Ca4YmvBi.js.map +0 -1
- package/dist/message-B5-6LeYl.js +0 -108
- package/dist/message-B5-6LeYl.js.map +0 -1
- package/dist/navigation-BTrEb5u4.js.map +0 -1
- package/dist/navigation-DqEITuD2.js.map +0 -1
- package/dist/navigation-row-recipes-BFpvGPGE.js.map +0 -1
- package/dist/overlays-DBqV0J_V.js +0 -982
- package/dist/overlays-DBqV0J_V.js.map +0 -1
- package/dist/page-BMBGjJY8.js.map +0 -1
- package/dist/page-header-BH41wCyY.js.map +0 -1
- package/dist/pagination-C29vvt3I.js.map +0 -1
- package/dist/popover-TInGXsjg.js.map +0 -1
- package/dist/popover.recipes-zgBhMlUu.js.map +0 -1
- package/dist/primitives-DKPOGVpj.js.map +0 -1
- package/dist/rich-text-editor-BZSJchAF.js +0 -575
- package/dist/rich-text-editor-BZSJchAF.js.map +0 -1
- package/dist/rich-text-editor.recipes-DxvOE0Lp.js.map +0 -1
- package/dist/scroll-area-BheMQ270.js.map +0 -1
- package/dist/select-B2mb-qN2.js +0 -108
- package/dist/select-B2mb-qN2.js.map +0 -1
- package/dist/sheet-vOUloJ4O.js.map +0 -1
- package/dist/sidebar-C3UKkbC5.js.map +0 -1
- package/dist/sidebar-CNBKFDRW.js.map +0 -1
- package/dist/smart-card-B5FcKODh.js.map +0 -1
- package/dist/structure.recipes-DjqnBpwz.js.map +0 -1
- package/dist/surface-recipes-CQfRr-VL.js.map +0 -1
- package/dist/table-DnlAJ-xR.js.map +0 -1
- package/dist/table-ghtAQ-JJ.js +0 -1424
- package/dist/table-ghtAQ-JJ.js.map +0 -1
- package/dist/tabs-DY09eoZg.js +0 -187
- package/dist/tabs-DY09eoZg.js.map +0 -1
- package/dist/text-inputs-BhOcedTo.js +0 -331
- package/dist/text-inputs-BhOcedTo.js.map +0 -1
- package/dist/text.styles-BwB7vAF2.js.map +0 -1
- package/dist/timelines-CnZ2S_Gr.js.map +0 -1
- package/dist/typography-Cv8MT-82.js +0 -96
- package/dist/typography-Cv8MT-82.js.map +0 -1
- package/dist/ui-provider-CftIB6TY.js.map +0 -1
- package/dist/upload-DIzw1dx1.js.map +0 -1
- package/dist/upload-queue-xRJ3qDmd.js.map +0 -1
- package/dist/utils-C2EKeIw3.js +0 -72
- package/dist/utils-C2EKeIw3.js.map +0 -1
- package/dist/value-inputs-Co1fu-xv.js +0 -824
- package/dist/value-inputs-Co1fu-xv.js.map +0 -1
- package/dist/workspace-Cbqz4FzN.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comments-u5L0OGip.js","names":["ImageIcon","_Fragment","NumberValue","_Fragment","useCommentsUIDefaults","useCommentsConfig","useDatesConfig","cn","TextButton","Text","DisplayLabel","TextLink","Tooltip","TooltipTrigger","TooltipContent","TooltipProvider","Button","Stack","rowBlockPaddingClasses","useOverlayVisibility","ConfirmDialog","sanitizeHtml","contentTypographyClassName","RichText","SecondaryValue","FileSize","Percent","Number$1","RelativeTime","AvatarFallback","Avatar","AvatarImage","Badge","fieldAffordanceRecipes","PopoverTrigger","Popover","EmptyState","RichTextEditor","useMentions","MentionInlineSuggestions","MentionContent","MentionPicker","parseMentionsFromHtml","Fragment$1","defaultCommentsStrings","useResolvedStrings","useStrings","propStrings","useResolvedAccessors","dates","useMemo","propAccessors","useComments","options","composerMode","setComposerMode","useState","isSubmitting","setIsSubmitting","isSubmittingRef","useRef","formErrors","setFormErrors","resetKey","setResetKey","setSubmitting","useCallback","submitting","resetComposer","k","helpers","reportError","error","onError","comment","onUpdate","payload","values","onAfterMutate","onSubmit","onDelete","id","pickIcon","att","Image","FileText","File","Paperclip","CommentAttachmentChip","stringsProp","strings","url","accessors","attachment","name","Icon","isUploading","isFailed","meta","surface","compact","className","iconNode","Loader2","labelRow","onRetry","editable","onRemove","X","defaultAttachmentUploadStrings","useAttachmentUpload","attachments","setAttachmentsState","initialAttachments","inFlightRef","fileCacheRef","attachmentsRef","commitAttachments","list","next","onValueChangeRef","onValueChange","updateAttachment","a","patch","setAttachments","beginUpload","onUpload","controller","uploaded","message","err","addFiles","disabled","files","filesInput","pending","file","maxFiles","maxSize","removeAttachment","entry","retryAttachment","reset","useEffect","inFlight","cache","hasMeaningfulContent","html","CommentComposer","forwardRef","resourcesProp","onResourceSearchProp","attachmentsProp","maxAttachmentsProp","allowAttachmentsProp","resources","onResourceSearch","allowAttachments","maxAttachments","attachmentsConfig","editorRef","body","setBody","initialValues","editingComment","contentError","setContentError","attachmentError","setAttachmentError","mentions","attachmentUpload","handleCancel","onCancel","useImperativeHandle","ref","context","errors","handleSubmit","event","replyingTo","fileInputRef","handleAttachmentClick","handleFiles","hasAttachments","isEditing","isReplying","submitLabel","eyebrow","ComposerEyebrow","makeReplyEyebrow","extraToolbarItems","items","AtSign","canComment","submitButton","Send","cancelButton","attachmentChips","footerSlot","trailingSubmit","inlineSubmit","showFooterRow","kind","parsed","previous","m","byId","merged","p","placeholder","autoFocus","label","onClose","closeLabel","interpolateString","template","CommentEmpty","icon","MessageCircle","CommentContent","props","contentType","richContent","renderRichContent","renderReference","plainContent","decodeQuotedString","rawContent","Fragment","renderRichBlock","block","index","decoded","data","raw","text","stripHtml","level","createElement","sanitizedItems","item","caption","value","trimmed","FALLBACK_INITIAL","defaultGetMediaUrl","defaultGetMediaName","defaultGetStatusLabel","s","CommentItem","memo","allowReactionsProp","allowRepliesProp","allowReactions","allowReplies","resolvedGetMediaUrl","resolvedGetMediaName","resolvedGetStatusLabel","resolvedFormatRelativeTime","authorName","avatarUrl","fallbackInitial","tagList","tag","reactions","isPinned","isEdited","showStatus","statusLabel","canDeleteComment","canModerate","canEditComment","canReply","onReply","canReact","onReact","canPin","onPinToggle","canEdit","onEdit","canDelete","hasActions","attachmentConfirm","pendingAttachmentId","setPendingAttachmentId","requestAttachmentRemoval","attachmentId","Pin","renderAttachment","canRemoveAttachment","onAttachmentRemove","reaction","CornerDownRight","Smile","Pencil","Trash2","CommentTimeline","comments","defaultItem","renderItem","emptySlot","Comments","ui","composerPosition","title","confirmDelete","deleteConfirm","pendingDeleteId","setPendingDeleteId","commentsState","requestDelete","startReply","handleReply","commentId","composer","timeline","composerBlock","inner","ariaLabel"],"sources":["../src/components/features/comments/comments.strings.ts","../src/components/features/comments/comments-provider.tsx","../src/components/features/comments/hooks/use-comments.ts","../src/components/features/comments/partials/comment-attachment-chip.tsx","../src/components/features/comments/hooks/use-attachment-upload.ts","../src/components/features/comments/partials/comment-composer.tsx","../src/components/features/comments/partials/comment-empty.tsx","../src/components/features/comments/partials/comment-content.tsx","../src/components/features/comments/partials/comment-item.tsx","../src/components/features/comments/partials/comment-timeline.tsx","../src/components/features/comments/comments.tsx"],"sourcesContent":["/**\n * Strings for the Comments feature. Consumers override via the `strings`\n * prop on `<Comments>` / sub-components — values are\n * deep-merged over these defaults.\n */\nexport interface CommentsStrings {\n\t/** Card title — usually \"Comments\". Set to \"\" to hide. */\n\ttitle: string;\n\t/** Subtitle under the card title — optional. */\n\tsubtitle: string;\n\t/** Empty-state copy for the timeline. */\n\tempty: string;\n\t/** Empty-state secondary copy. */\n\temptyHint: string;\n\n\t// Composer ---------------------------------------------------------\n\t/** Composer rich-text placeholder. */\n\tcomposerPlaceholder: string;\n\t/** Submit label for new comments. */\n\tcomposerSubmit: string;\n\t/** Submit label while pending. */\n\tcomposerSubmitting: string;\n\t/** Submit label when editing. */\n\tcomposerSave: string;\n\t/** Required-content error. */\n\tinvalidContent: string;\n\t/** Cancel/dismiss draft. */\n\tcomposerCancel: string;\n\t/** \"Edit comment\" eyebrow shown above the composer in edit mode. */\n\tcomposerEditingEyebrow: string;\n\t/** \"Reply to {{name}}\" eyebrow shown above the composer in reply mode. */\n\tcomposerReplyingEyebrow: string;\n\n\t// Toolbar buttons --------------------------------------------------\n\tcomposerAttachmentLabel: string;\n\t/** Control that inserts a mention or link. */\n\tcomposerReferenceLabel: string;\n\t/** Heading of the insert-reference menu. */\n\tcomposerReferenceMenuTitle: string;\n\t/** Placeholder in the reference search field. */\n\tcomposerReferenceSearchPlaceholder: string;\n\t/** Shown when a reference search matches nothing. */\n\tcomposerReferenceEmpty: string;\n\t/** Shown while reference results are loading. */\n\tcomposerReferenceLoading: string;\n\n\t// Item -------------------------------------------------------------\n\tfallbackAuthor: string;\n\t/** Chip marking a pinned comment. */\n\tpinned: string;\n\t/** Suffix marking an edited comment. */\n\tedited: string;\n\t/** Trash button aria-label / tooltip. */\n\tdeleteLabel: string;\n\t/** Edit button label. */\n\teditLabel: string;\n\t/** Reply button label. */\n\treplyLabel: string;\n\t/** Pin/unpin button label. */\n\tpinLabel: string;\n\t/** Action that unpins a comment. */\n\tunpinLabel: string;\n\t/** \"More actions\" trigger aria-label. */\n\tmoreActionsLabel: string;\n\t/** Confirm-delete button label inside the action menu. */\n\tconfirmDeleteLabel: string;\n\t/** Title of the confirmation shown before a comment is deleted. */\n\tconfirmDeleteTitle: string;\n\t/** Title of the confirmation shown before an attachment is removed. */\n\tconfirmRemoveAttachmentTitle: string;\n\t/** Consequence of removing an attachment from a posted comment. */\n\tconfirmRemoveAttachmentDescription: string;\n\t/** Sentence explaining the consequence before the delete is committed. */\n\tconfirmDeleteDescription: string;\n\n\t// Attachments ------------------------------------------------------\n\tattachmentFallback: string;\n\t/** Removes an attachment — staged in the composer, or posted on a comment. */\n\tattachmentRemoveLabel: string;\n\t/** Shown while an attachment uploads. */\n\tattachmentUploadingLabel: string;\n\t/** Shown when an attachment upload fails. */\n\tattachmentFailedLabel: string;\n\t/** Shown when a file exceeds the size limit. */\n\tattachmentTooLargeError: string;\n\t/** Shown when too many files are attached. */\n\tattachmentTooManyError: string;\n\t/** Action that retries a failed upload. */\n\tattachmentRetryLabel: string;\n\t/** Action that downloads an attachment. */\n\tattachmentDownloadLabel: string;\n\n\t// Reactions --------------------------------------------------------\n\taddReactionLabel: string;\n\t/** Reaction button name; interpolates {{emoji}} and {{count}}. Optional for existing complete string objects. */\n\treactionLabel?: string;\n\n\t// Misc -------------------------------------------------------------\n\tshowRepliesLabel: string;\n\t/** Control that collapses a reply thread. */\n\thideRepliesLabel: string;\n}\n\nexport const defaultCommentsStrings: CommentsStrings = {\n\ttitle: 'Comments',\n\tsubtitle: '',\n\tempty: 'No comments yet.',\n\temptyHint: 'Start the conversation — your team will see it instantly.',\n\n\tcomposerPlaceholder: 'Write a comment…',\n\tcomposerSubmit: 'Post comment',\n\tcomposerSubmitting: 'Posting…',\n\tcomposerSave: 'Save changes',\n\tinvalidContent: 'Comment cannot be empty.',\n\tcomposerCancel: 'Cancel',\n\tcomposerEditingEyebrow: 'Editing comment',\n\tcomposerReplyingEyebrow: 'Replying to {{name}}',\n\n\tcomposerAttachmentLabel: 'Attach file',\n\tcomposerReferenceLabel: 'Mention or link',\n\tcomposerReferenceMenuTitle: 'Insert reference',\n\tcomposerReferenceSearchPlaceholder: 'Search…',\n\tcomposerReferenceEmpty: 'No matches.',\n\tcomposerReferenceLoading: 'Searching…',\n\n\tfallbackAuthor: 'Anonymous',\n\tpinned: 'Pinned',\n\tedited: 'edited',\n\tdeleteLabel: 'Delete',\n\teditLabel: 'Edit',\n\treplyLabel: 'Reply',\n\tpinLabel: 'Pin',\n\tunpinLabel: 'Unpin',\n\tmoreActionsLabel: 'More actions',\n\tconfirmDeleteLabel: 'Delete comment',\n\tconfirmDeleteTitle: 'Delete this comment?',\n\tconfirmRemoveAttachmentTitle: 'Remove this attachment?',\n\tconfirmRemoveAttachmentDescription: 'The file is detached from the comment for everyone. This cannot be undone.',\n\tconfirmDeleteDescription: 'The comment and its replies are removed for everyone. This cannot be undone.',\n\n\tattachmentFallback: 'Attachment',\n\tattachmentRemoveLabel: 'Remove attachment',\n\tattachmentUploadingLabel: 'Uploading…',\n\tattachmentFailedLabel: 'Upload failed',\n\tattachmentTooLargeError: 'File is too large.',\n\tattachmentTooManyError: 'Too many attachments.',\n\tattachmentRetryLabel: 'Retry',\n\tattachmentDownloadLabel: 'Download',\n\n\taddReactionLabel: 'Add reaction',\n\treactionLabel: 'Reaction {{emoji}}: {{count}}',\n\n\tshowRepliesLabel: 'Show replies',\n\thideRepliesLabel: 'Hide replies',\n};\n","/**\n * Comments — internal helper hooks for resolving strings and accessors.\n *\n * Rationale: the previous `<CommentsProvider>` is gone. Library-wide\n * Per-mount overrides flow as direct props on `<Comments>` and its partials.\n * Date formatting may still inherit the app-wide dates configuration.\n *\n * Resolution order everywhere:\n *\n * props.strings ← deep-merged over `defaultCommentsStrings`\n * props.accessor.X ← falls back to UIProvider's dates formatter, then\n * to a built-in default at the call site.\n */\nimport { useMemo } from 'react';\n\nimport { useStrings, type StringsProp } from '../../../lib/strings';\nimport { useDatesConfig } from '../../../lib/ui-provider';\n\nimport {\n\tdefaultCommentsStrings,\n\ttype CommentsStrings,\n} from './comments.strings';\nimport type { CommentsAccessors } from './comments.types';\n\n/**\n * Resolve final strings by merging defaults → component prop. Stable\n * identity when the prop reference is unchanged.\n */\nexport function useResolvedStrings(\n\tpropStrings?: StringsProp<CommentsStrings>,\n): CommentsStrings {\n\treturn useStrings(defaultCommentsStrings, propStrings);\n}\n\n/**\n * Resolve accessors. Order:\n * 1. explicit prop accessor\n * 2. the UIProvider date formatter for relative time\n * 3. caller's own fallback when neither is present (handled at call site)\n */\nexport function useResolvedAccessors(\n\tpropAccessors?: CommentsAccessors,\n): CommentsAccessors {\n\tconst dates = useDatesConfig();\n\treturn useMemo<CommentsAccessors>(\n\t\t() => ({\n\t\t\tgetMediaUrl: propAccessors?.getMediaUrl,\n\t\t\tgetMediaName: propAccessors?.getMediaName,\n\t\t\tgetStatusLabel: propAccessors?.getStatusLabel,\n\t\t\tformatRelativeTime:\n\t\t\t\tpropAccessors?.formatRelativeTime ?? dates.formatRelativeTime,\n\t\t}),\n\t\t[propAccessors, dates.formatRelativeTime],\n\t);\n}\n","/**\n * useComments — headless state machine for the Comments feature.\n *\n * Tracks composer mode (idle | replying | editing), submit/delete\n * helpers, error state, and resetKey bumping. The default `<Comments>`\n * component composes this hook; consumers building a fully custom UI\n * can use it directly.\n */\nimport { useCallback, useMemo, useRef, useState } from 'react';\n\nimport type {\n\tCommentData,\n\tCommentFormValues,\n\tCommentSubmitHelpers,\n\tCommentUser,\n\tCommentsConfig,\n} from '../comments.types';\n\nexport type ComposerMode<\n\tTResource extends string = string,\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n> =\n\t| { kind: 'idle' }\n\t| { kind: 'editing'; comment: CommentData<TUser, TMeta, TResource> }\n\t| { kind: 'replying'; commentId: string; authorName?: string };\n\nexport interface UseCommentsOptions<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n> {\n\tonSubmit?: CommentsConfig<TUser, TMeta, TResource>['onSubmit'];\n\tonUpdate?: CommentsConfig<TUser, TMeta, TResource>['onUpdate'];\n\tonDelete?: CommentsConfig<TUser, TMeta, TResource>['onDelete'];\n\tonAfterMutate?: CommentsConfig<TUser, TMeta, TResource>['onAfterMutate'];\n\tonError?: CommentsConfig<TUser, TMeta, TResource>['onError'];\n}\n\nexport interface UseCommentsReturn<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n> {\n\tcomposerMode: ComposerMode<TResource, TUser, TMeta>;\n\tisSubmitting: boolean;\n\tformErrors: Record<string, string>;\n\tresetKey: number;\n\n\tstartReply: (comment: CommentData<TUser, TMeta, TResource>) => void;\n\tstartEdit: (comment: CommentData<TUser, TMeta, TResource>) => void;\n\tcancelComposerMode: () => void;\n\n\tsubmit: (values: CommentFormValues<TResource>) => Promise<void>;\n\tdeleteComment: (id: string) => Promise<void>;\n\n\t/** Imperative reset — bumps `resetKey` so the composer clears itself. */\n\tresetComposer: () => void;\n\t/** Helpers exposed to onSubmit/onUpdate. */\n\thelpers: CommentSubmitHelpers;\n}\n\nexport function useComments<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n>(\n\toptions: UseCommentsOptions<TUser, TMeta, TResource> = {},\n): UseCommentsReturn<TUser, TMeta, TResource> {\n\tconst { onSubmit, onUpdate, onDelete, onAfterMutate, onError } = options;\n\n\tconst [composerMode, setComposerMode] = useState<\n\t\tComposerMode<TResource, TUser, TMeta>\n\t>({\n\t\tkind: 'idle',\n\t});\n\tconst [isSubmitting, setIsSubmitting] = useState(false);\n\tconst isSubmittingRef = useRef(false);\n\tconst [formErrors, setFormErrors] = useState<Record<string, string>>({});\n\tconst [resetKey, setResetKey] = useState(0);\n\n\tconst setSubmitting = useCallback((submitting: boolean) => {\n\t\tisSubmittingRef.current = submitting;\n\t\tsetIsSubmitting(submitting);\n\t}, []);\n\n\tconst resetComposer = useCallback(() => {\n\t\tsetResetKey((k) => k + 1);\n\t\tsetComposerMode({ kind: 'idle' });\n\t\tsetFormErrors({});\n\t\tsetSubmitting(false);\n\t}, [setSubmitting]);\n\n\tconst helpers = useMemo<CommentSubmitHelpers>(\n\t\t() => ({\n\t\t\tsetErrors: setFormErrors,\n\t\t\treset: resetComposer,\n\t\t\tsetSubmitting,\n\t\t}),\n\t\t[resetComposer, setSubmitting],\n\t);\n\n\tconst reportError = useCallback(\n\t\t(error: unknown) => {\n\t\t\ttry {\n\t\t\t\tonError?.(error);\n\t\t\t} catch (callbackError) {\n\t\t\t\tif (import.meta.env?.DEV) {\n\t\t\t\t\tconsole.warn('[Comments] onError callback failed.', callbackError);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[onError],\n\t);\n\n\tconst startReply = useCallback(\n\t\t(comment: CommentData<TUser, TMeta, TResource>) => {\n\t\t\tif (!comment.id) return;\n\t\t\tsetFormErrors({});\n\t\t\tsetComposerMode({\n\t\t\t\tkind: 'replying',\n\t\t\t\tcommentId: comment.id,\n\t\t\t\tauthorName: comment.user?.name,\n\t\t\t});\n\t\t},\n\t\t[],\n\t);\n\n\tconst startEdit = useCallback(\n\t\t(comment: CommentData<TUser, TMeta, TResource>) => {\n\t\t\tif (!comment.id) return;\n\t\t\tsetFormErrors({});\n\t\t\tsetComposerMode({ kind: 'editing', comment });\n\t\t},\n\t\t[],\n\t);\n\n\tconst cancelComposerMode = useCallback(() => {\n\t\tresetComposer();\n\t}, [resetComposer]);\n\n\tconst submit = useCallback(\n\t\tasync (values: CommentFormValues<TResource>) => {\n\t\t\tif (composerMode.kind === 'editing' && composerMode.comment.id) {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tif (isSubmittingRef.current) return;\n\n\t\t\t\tconst payload = {\n\t\t\t\t\t...values,\n\t\t\t\t\teditingId: composerMode.comment.id,\n\t\t\t\t};\n\t\t\t\tsetSubmitting(true);\n\t\t\t\tsetFormErrors({});\n\t\t\t\ttry {\n\t\t\t\t\tawait onUpdate(composerMode.comment.id, payload, helpers);\n\t\t\t\t\tonAfterMutate?.('update', payload);\n\t\t\t\t} catch (error) {\n\t\t\t\t\treportError(error);\n\t\t\t\t} finally {\n\t\t\t\t\tsetSubmitting(false);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!onSubmit) return;\n\t\t\tif (isSubmittingRef.current) return;\n\n\t\t\tconst payload: CommentFormValues<TResource> =\n\t\t\t\tcomposerMode.kind === 'replying'\n\t\t\t\t\t? { ...values, replyToId: composerMode.commentId }\n\t\t\t\t\t: values;\n\n\t\t\tsetSubmitting(true);\n\t\t\tsetFormErrors({});\n\t\t\ttry {\n\t\t\t\tawait onSubmit(payload, helpers);\n\t\t\t\tonAfterMutate?.('create', payload);\n\t\t\t} catch (error) {\n\t\t\t\treportError(error);\n\t\t\t} finally {\n\t\t\t\tsetSubmitting(false);\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tcomposerMode,\n\t\t\thelpers,\n\t\t\tonAfterMutate,\n\t\t\tonSubmit,\n\t\t\tonUpdate,\n\t\t\treportError,\n\t\t\tsetSubmitting,\n\t\t],\n\t);\n\n\tconst deleteComment = useCallback(\n\t\tasync (id: string) => {\n\t\t\tif (!onDelete || !id) return;\n\t\t\ttry {\n\t\t\t\tawait onDelete(id);\n\t\t\t\tonAfterMutate?.('delete', { commentId: id });\n\t\t\t} catch (error) {\n\t\t\t\treportError(error);\n\t\t\t}\n\t\t},\n\t\t[onAfterMutate, onDelete, reportError],\n\t);\n\n\treturn {\n\t\tcomposerMode,\n\t\tisSubmitting,\n\t\tformErrors,\n\t\tresetKey,\n\t\tstartReply,\n\t\tstartEdit,\n\t\tcancelComposerMode,\n\t\tsubmit,\n\t\tdeleteComment,\n\t\tresetComposer,\n\t\thelpers,\n\t};\n}\n","/**\n * CommentAttachmentChip — small attachment pill used in the composer draft\n * and the timeline. Single inline row: icon + name · size, with progress /\n * error states overlaid on the same line. Editable mode reveals a remove\n * button; failed uploads expose a retry pill.\n */\nimport { File, FileText, Image as ImageIcon, Loader2, Paperclip, X } from 'lucide-react';\nimport type { FC, ReactNode } from 'react';\n\nimport { TextButton } from '../../../base/buttons';\nimport { FileSize, Percent, SecondaryValue } from '../../../primitives';\nimport { Text, TextLink } from '../../../typography';\nimport { useStrings, type StringsProp } from '../../../../lib/strings';\nimport { cn } from '../../../../lib/utils';\nimport { rowBlockPaddingClasses } from '../../../../lib/row-recipes';\nimport { fieldAffordanceRecipes } from '../../../../lib/field-affordance-recipes';\n\nimport type {\n\t\tCommentAttachment,\n\t\tCommentsAccessors,\n} from '../comments.types';\nimport {\n\t\tdefaultCommentsStrings,\n\t\ttype CommentsStrings,\n} from '../comments.strings';\n\nexport interface CommentAttachmentChipProps {\n\t\t/** The attachment this chip represents. */\n\t\tattachment: CommentAttachment;\n\t\t/** Editable mode shows a remove button. */\n\t\teditable?: boolean;\n\t\t/** Fired when an entry is removed. */\n\t\tonRemove?: (id: string) => void;\n\t\t/** Fired when the user retries after an entry failure. */\n\t\tonRetry?: (id: string) => void;\n\t\t/** Reads the fields this surface needs off your own shape. */\n\t\taccessors?: CommentsAccessors;\n\t\t/** Overrides this surface's own copy. */\n\t\tstrings?: StringsProp<CommentsStrings>;\n\t\t/** Compact chips have smaller text and tighter padding. */\n\t\tcompact?: boolean;\n\t\t/** Merged onto the outermost node. */\n\t\tclassName?: string;\n}\n\nfunction pickIcon(att: CommentAttachment) {\n\t\tif (att.mimeType?.startsWith('image/')) return ImageIcon;\n\t\tif (att.mimeType === 'application/pdf') return FileText;\n\t\tif (att.mimeType?.startsWith('text/')) return FileText;\n\t\tif (att.mimeType) return File;\n\t\treturn Paperclip;\n}\n\nexport const CommentAttachmentChip: FC<CommentAttachmentChipProps> = ({\n\t\tattachment,\n\t\teditable = false,\n\t\tonRemove,\n\t\tonRetry,\n\t\taccessors,\n\t\tstrings: stringsProp,\n\t\tcompact = false,\n\t\tclassName,\n}) => {\n\t\tconst strings = useStrings(defaultCommentsStrings, stringsProp);\n\n\t\tconst url = accessors?.getMediaUrl?.(attachment) ?? attachment.url;\n\t\tconst name =\n\t\t\t\taccessors?.getMediaName?.(attachment) ??\n\t\t\t\tattachment.name ??\n\t\t\t\tstrings.attachmentFallback;\n\t\tconst Icon = pickIcon(attachment);\n\n\t\tconst isUploading = attachment.status === 'uploading';\n\t\tconst isFailed = attachment.status === 'failed';\n\t\tconst meta: ReactNode = isUploading\n\t\t\t\t? (\n\t\t\t\t\t\t<SecondaryValue size=\"xs\" className=\"shrink-0\">\n\t\t\t\t\t\t\t\t{strings.attachmentUploadingLabel}\n\t\t\t\t\t\t\t\t{typeof attachment.progress === 'number' ? (\n\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t\t\t\t\t<Percent\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue={Math.round(attachment.progress)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tscaled\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\talign=\"left\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"secondary\"\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</SecondaryValue>\n\t\t\t\t)\n\t\t\t\t: isFailed\n\t\t\t\t\t? (\n\t\t\t\t\t\t\t<SecondaryValue size=\"xs\" className=\"shrink-0\">\n\t\t\t\t\t\t\t\t\t{attachment.error ?? strings.attachmentFailedLabel}\n\t\t\t\t\t\t\t</SecondaryValue>\n\t\t\t\t\t)\n\t\t\t\t\t: typeof attachment.size === 'number'\n\t\t\t\t\t\t? (\n\t\t\t\t\t\t\t<FileSize value={attachment.size} size=\"xs\" className=\"shrink-0\" />\n\t\t\t\t\t\t)\n\t\t\t\t\t\t: null;\n\n\t\tconst surface = cn(\n\t\t'comment-attachment-chip--component',\n\t\t\t\t'relative inline-flex min-w-0 max-w-[20rem] items-center gap-space-sm rounded-radius',\n\t\t\t\t'ring-1 ring-inset transition-colors',\n\t\t\t\tcompact ? 'px-control-xs' : 'px-control-sm',\n\t\t\t\trowBlockPaddingClasses.compact,\n\t\t\t\tisFailed\n\t\t\t\t\t\t? 'bg-destructive/[0.04] ring-destructive/30 hover:bg-destructive/[0.08]'\n\t\t\t\t\t\t: 'bg-foreground/[0.03] ring-border/60 hover:bg-foreground/[0.06]',\n\t\t\t\tclassName,\n\t\t);\n\n\t\tconst iconNode = isUploading ? (\n\t\t\t\t<Loader2\n\t\t\t\t\t\tclassName={cn('shrink-0 animate-spin text-muted-foreground', 'size-icon-md')}\n\t\t\t\t\t\taria-hidden\n\t\t\t\t/>\n\t\t) : (\n\t\t\t\t<Icon\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'shrink-0',\n\t\t\t\t\t\t\t\t'size-icon-md',\n\t\t\t\t\t\t\t\tisFailed ? 'text-destructive' : 'text-muted-foreground',\n\t\t\t\t\t\t)}\n\t\t\t\t\t\taria-hidden\n\t\t\t\t/>\n\t\t);\n\n\t\tconst labelRow = (\n\t\t\t\t<span className=\"inline-flex min-w-0 items-baseline gap-space-sm\">\n\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\t\tweight=\"medium\"\n\t\t\t\t\t\t\t\tclassName={cn('truncate', isFailed && 'text-destructive')}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{name}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t{meta}\n\t\t\t\t</span>\n\t\t);\n\n\t\tconst isInteractive = !!url && !isUploading && !isFailed;\n\n\t\treturn (\n\t\t\t\t<div className={surface}>\n\t\t\t\t\t\t{iconNode}\n\t\t\t\t\t\t{isInteractive ? (\n\t\t\t\t<TextLink\n\t\t\t\t\thref={url}\n\t\t\t\t\tsize=\"inherit\"\n\t\t\t\t\tunderline={false}\n\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\trel=\"noreferrer noopener\"\n\t\t\t\t\tclassName=\"inline-flex min-w-0 flex-1 items-baseline gap-space-sm hover:underline\"\n\t\t\t\t\t\t\t\t\t\taria-label={strings.attachmentDownloadLabel}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{labelRow}\n\t\t\t\t</TextLink>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\tlabelRow\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{isUploading && typeof attachment.progress === 'number' && (\n\t\t\t\t\t\t\t\t<div className=\"bg-primary/15 absolute bottom-0 left-2 right-2 h-px overflow-hidden rounded-full\">\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"bg-primary h-full transition-[width]\"\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\twidth: `${Math.min(100, Math.max(0, attachment.progress))}%`,\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{isFailed && onRetry && (\n\t\t\t\t\t\t\t\t<TextButton\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => onRetry(attachment.id)}\n\t\t\t\t\t\t\t\t\t\tclassName=\"shrink-0 text-destructive decoration-destructive/30 hover:decoration-destructive/60\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<Text tag=\"span\" size=\"xs\" weight=\"medium\" className=\"text-inherit\">{strings.attachmentRetryLabel}</Text>\n\t\t\t\t\t\t\t\t</TextButton>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{editable && onRemove && (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={() => onRemove(attachment.id)}\n\t\t\t\t\t\t\t\t\t\tclassName={cn(fieldAffordanceRecipes.target, fieldAffordanceRecipes.focus, fieldAffordanceRecipes.toggle)}\n\t\t\t\t\t\t\t\t\t\taria-label={strings.attachmentRemoveLabel}\n\t\t\t\t\t\t\t\t\t\ttitle={strings.attachmentRemoveLabel}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<X className={fieldAffordanceRecipes.icon} aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t);\n};\n","/**\n * useAttachmentUpload — manages a list of in-flight + uploaded\n * `CommentAttachment`s for a comment composer.\n *\n * Pass the consumer-supplied `onUpload` callback directly via the\n * `attachments` prop on `<Comments>` (or `<CommentComposer>`). Aborts\n * in-flight uploads when an attachment is removed.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useStrings, type StringsProp } from '../../../../lib/strings';\nimport { defaultCommentsStrings, type CommentsStrings } from '../comments.strings';\n\nimport type {\n\tCommentAttachment,\n\tCommentsAttachmentsConfig,\n} from '../comments.types';\n\ninterface InFlightEntry {\n\tcontroller: AbortController;\n}\n\nconst defaultAttachmentUploadStrings = {\n\tattachmentTooLargeError: defaultCommentsStrings.attachmentTooLargeError,\n\tattachmentTooManyError: defaultCommentsStrings.attachmentTooManyError,\n\tattachmentFailedLabel: defaultCommentsStrings.attachmentFailedLabel,\n};\n\nexport interface UseAttachmentUploadOptions extends CommentsAttachmentsConfig {\n\t/** Initial attachments — useful when editing an existing comment. */\n\tinitialAttachments?: ReadonlyArray<CommentAttachment>;\n\t/** Fires when the list of uploaded attachments changes. */\n\tonValueChange?: (attachments: ReadonlyArray<CommentAttachment>) => void;\n\t/** Fires when a validation or upload error happens. */\n\tonError?: (error: string) => void;\n\t/** Validation and non-Error upload fallback copy; omitted keys use Comments defaults.\n\t * Error objects retain their caller-supplied message. */\n\tstrings?: StringsProp<Pick<CommentsStrings, 'attachmentTooLargeError' | 'attachmentTooManyError' | 'attachmentFailedLabel'>>;\n}\n\nexport interface UseAttachmentUploadReturn {\n\t/** All attachments — uploading + uploaded + failed. */\n\tattachments: ReadonlyArray<CommentAttachment>;\n\t/** Subset of attachments that finished uploading. Use this in the form payload. */\n\tuploadedAttachments: ReadonlyArray<CommentAttachment>;\n\t/** True while at least one upload is in flight. */\n\tisUploading: boolean;\n\t/** Add files. Validates against `maxSize` / `maxFiles` first. */\n\taddFiles: (files: ReadonlyArray<File> | FileList) => void;\n\t/** Remove an attachment by id (aborts in-flight uploads). */\n\tremoveAttachment: (id: string) => void;\n\t/** Retry a failed upload. */\n\tretryAttachment: (id: string) => void;\n\t/** Replace the list (used when editing or after submit). */\n\tsetAttachments: (attachments: ReadonlyArray<CommentAttachment>) => void;\n\t/** Clear the list and abort everything in flight. */\n\treset: () => void;\n}\n\nexport function useAttachmentUpload(\n\toptions: UseAttachmentUploadOptions = {},\n): UseAttachmentUploadReturn {\n\tconst {\n\t\tonUpload,\n\t\tmaxSize,\n\t\tmaxFiles,\n\t\t// `accept` is consumed by the surrounding `<input type=\"file\"\n\t\t// accept>` element, not here — destructuring is intentional\n\t\t// even though we don't reference it inside the hook.\n\t\tdisabled,\n\t\tinitialAttachments,\n\t\tonValueChange,\n\t\tonError,\n\t\tstrings: stringsProp,\n\t} = options;\n\tconst strings = useStrings(defaultAttachmentUploadStrings, stringsProp);\n\n\tconst [attachments, setAttachmentsState] = useState<CommentAttachment[]>(() =>\n\t\tinitialAttachments ? [...initialAttachments] : [],\n\t);\n\tconst inFlightRef = useRef<Map<string, InFlightEntry>>(new Map());\n\tconst fileCacheRef = useRef<Map<string, File>>(new Map());\n\tconst attachmentsRef = useRef(attachments);\n\t// Keep sequential picks and async updates current without calling consumers\n\t// from a React state updater (which StrictMode may evaluate more than once).\n\tconst commitAttachments = useCallback((next: ReadonlyArray<CommentAttachment>) => {\n\t\tconst list = [...next];\n\t\tattachmentsRef.current = list;\n\t\tsetAttachmentsState(list);\n\t}, []);\n\tconst onValueChangeRef = useRef(onValueChange);\n\tonValueChangeRef.current = onValueChange;\n\n\tconst updateAttachment = useCallback(\n\t\t(id: string, patch: Partial<CommentAttachment>) => {\n\t\t\tcommitAttachments(attachmentsRef.current.map((a) => (a.id === id ? { ...a, ...patch } : a)));\n\t\t},\n\t\t[commitAttachments],\n\t);\n\n\tconst setAttachments = useCallback(\n\t\t(next: ReadonlyArray<CommentAttachment>) => {\n\t\t\tcommitAttachments(next);\n\t\t},\n\t\t[commitAttachments],\n\t);\n\n\tconst beginUpload = useCallback(\n\t\t(id: string, file: File) => {\n\t\t\tif (!onUpload || !fileCacheRef.current.has(id)) return;\n\t\t\tconst controller = new AbortController();\n\t\t\tinFlightRef.current.set(id, { controller });\n\n\t\t\tupdateAttachment(id, {\n\t\t\t\tstatus: 'uploading',\n\t\t\t\tprogress: 0,\n\t\t\t\terror: undefined,\n\t\t\t});\n\n\t\t\tconst onProgress = (progress: number) => {\n\t\t\t\tif (controller.signal.aborted) return;\n\t\t\t\tupdateAttachment(id, { progress });\n\t\t\t};\n\n\t\t\tonUpload({ file, onProgress, signal: controller.signal })\n\t\t\t\t.then((uploaded) => {\n\t\t\t\t\tif (controller.signal.aborted) return;\n\t\t\t\t\tinFlightRef.current.delete(id);\n\t\t\t\t\tupdateAttachment(id, {\n\t\t\t\t\t\t...uploaded,\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tstatus: 'uploaded',\n\t\t\t\t\t\tprogress: 100,\n\t\t\t\t\t\terror: undefined,\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tinFlightRef.current.delete(id);\n\t\t\t\t\tif (controller.signal.aborted) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst message =\n\t\t\t\t\t\terr instanceof Error ? err.message : strings.attachmentFailedLabel;\n\t\t\t\t\tupdateAttachment(id, {\n\t\t\t\t\t\tstatus: 'failed',\n\t\t\t\t\t\terror: message,\n\t\t\t\t\t});\n\t\t\t\t\tonError?.(message);\n\t\t\t\t});\n\t\t},\n\t\t[onError, onUpload, strings.attachmentFailedLabel, updateAttachment],\n\t);\n\n\tconst addFiles = useCallback(\n\t\t(filesInput: ReadonlyArray<File> | FileList) => {\n\t\t\tif (disabled || !onUpload) return;\n\t\t\tconst files = Array.from(filesInput);\n\t\t\tif (files.length === 0) return;\n\n\t\t\tconst next = [...attachmentsRef.current];\n\t\t\tconst pending: Array<{id: string; file: File}> = [];\n\t\t\tfor (const file of files) {\n\t\t\t\tif (\n\t\t\t\t\ttypeof maxFiles === 'number' &&\n\t\t\t\t\tnext.length >= maxFiles\n\t\t\t\t) {\n\t\t\t\t\tonError?.(strings.attachmentTooManyError);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\ttypeof maxSize === 'number' &&\n\t\t\t\t\tfile.size > maxSize\n\t\t\t\t) {\n\t\t\t\t\tonError?.(strings.attachmentTooLargeError);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst id =\n\t\t\t\t\ttypeof crypto !== 'undefined' && 'randomUUID' in crypto\n\t\t\t\t\t\t? crypto.randomUUID()\n\t\t\t\t\t\t: `att-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n\n\t\t\t\tfileCacheRef.current.set(id, file);\n\n\t\t\t\tnext.push({\n\t\t\t\t\tid,\n\t\t\t\t\tname: file.name,\n\t\t\t\t\tsize: file.size,\n\t\t\t\t\tmimeType: file.type,\n\t\t\t\t\tstatus: 'uploading',\n\t\t\t\t\tprogress: 0,\n\t\t\t\t});\n\n\t\t\t\tpending.push({id, file});\n\t\t\t}\n\t\t\tcommitAttachments(next);\n\t\t\tfor (const {id, file} of pending) queueMicrotask(() => beginUpload(id, file));\n\t\t},\n\t\t[beginUpload, commitAttachments, disabled, maxFiles, maxSize, onError, onUpload, strings.attachmentTooLargeError, strings.attachmentTooManyError],\n\t);\n\n\tconst removeAttachment = useCallback((id: string) => {\n\t\tconst entry = inFlightRef.current.get(id);\n\t\tif (entry) {\n\t\t\tentry.controller.abort();\n\t\t\tinFlightRef.current.delete(id);\n\t\t}\n\t\tfileCacheRef.current.delete(id);\n\t\tcommitAttachments(attachmentsRef.current.filter((a) => a.id !== id));\n\t}, [commitAttachments]);\n\n\tconst retryAttachment = useCallback(\n\t\t(id: string) => {\n\t\t\tconst file = fileCacheRef.current.get(id);\n\t\t\tif (!file) return;\n\t\t\tbeginUpload(id, file);\n\t\t},\n\t\t[beginUpload],\n\t);\n\n\tconst reset = useCallback(() => {\n\t\tfor (const entry of inFlightRef.current.values()) {\n\t\t\tentry.controller.abort();\n\t\t}\n\t\tinFlightRef.current.clear();\n\t\tfileCacheRef.current.clear();\n\t\tcommitAttachments([]);\n\t}, [commitAttachments]);\n\n\tuseEffect(() => {\n\t\tonValueChangeRef.current?.(attachments);\n\t}, [attachments]);\n\n\tuseEffect(() => {\n\t\tconst inFlight = inFlightRef.current;\n\t\tconst cache = fileCacheRef.current;\n\t\treturn () => {\n\t\t\tfor (const entry of inFlight.values()) {\n\t\t\t\tentry.controller.abort();\n\t\t\t}\n\t\t\tcache.clear();\n\t\t};\n\t}, []);\n\n\tconst uploadedAttachments = useMemo(\n\t\t() => attachments.filter((a) => a.status === 'uploaded' || !a.status),\n\t\t[attachments],\n\t);\n\n\tconst isUploading = useMemo(\n\t\t() => attachments.some((a) => a.status === 'uploading'),\n\t\t[attachments],\n\t);\n\n\treturn {\n\t\tattachments,\n\t\tuploadedAttachments,\n\t\tisUploading,\n\t\taddFiles,\n\t\tremoveAttachment,\n\t\tretryAttachment,\n\t\tsetAttachments,\n\t\treset,\n\t};\n}\n","/**\n * CommentComposer — TipTap-backed rich text editor with inline reference\n * picker and attachment uploader. Default composer for `<Comments>`.\n *\n * Mention/reference handling is delegated to the shared\n * `features/mentions` module: `useMentions` drives picker state +\n * caret-trigger detection, `<MentionPicker>` renders the popover, and\n * `<MentionChip>` renders draft-list chips. The same primitives power\n * inline references in `features/activities`.\n */\nimport { AtSign, Loader2, Paperclip, Send, X } from 'lucide-react';\nimport {\n\t\tforwardRef,\n\t\tuseEffect,\n\t\tuseImperativeHandle,\n\t\tuseMemo,\n\t\tuseRef,\n\t\tuseState,\n} from 'react';\nimport type { ReactNode } from 'react';\nimport type { ReactElement, RefAttributes } from 'react';\n\nimport { Button } from '../../../base/buttons';\nimport { Popover, PopoverTrigger } from '../../../base/popover';\nimport { Stack } from '../../../base/structure';\nimport { DisplayLabel, Text } from '../../../typography';\nimport {\n\t\tRichTextEditor,\n\t\ttype RichTextEditorHandle,\n\t\ttype RichTextEditorToolbarItem,\n} from '../../rich-text-editor/rich-text-editor';\nimport {\n\t\tMentionInlineSuggestions,\n\t\tMentionPicker,\n\t\tparseMentionsFromHtml,\n\t\tuseMentions,\n} from '../../mentions';\nimport { useResolvedStrings } from '../comments-provider';\nimport { interpolateString } from '../../../../lib/strings';\nimport { rowBlockPaddingClasses } from '../../../../lib/row-recipes';\nimport { cn } from '../../../../lib/utils';\nimport { fieldAffordanceRecipes } from '../../../../lib/field-affordance-recipes';\nimport type {\n\t\tCommentComposerProps,\n\t\tCommentFormValues,\n} from '../comments.types';\nimport { CommentAttachmentChip } from './comment-attachment-chip';\nimport { useAttachmentUpload } from '../hooks/use-attachment-upload';\n\nexport interface CommentComposerHandle {\n\t\tfocus(): void;\n\t\tclear(): void;\n\t\t/** Imperatively set the draft body. */\n\t\tsetBody(html: string): void;\n}\n\nfunction hasMeaningfulContent(html: string): boolean {\n\t\tif (!html || typeof html !== 'string') return false;\n\t\tconst text = html.replace(/<[^>]*>/g, '').trim();\n\t\treturn text.length > 0;\n}\n\nconst CommentComposerBase = forwardRef<\n\t\tCommentComposerHandle,\n\t\tCommentComposerProps\n>(function CommentComposer(\n\t\t{\n\t\t\t\tcontext,\n\t\t\t\tcanComment = true,\n\t\t\t\tsubmitting = false,\n\t\t\t\terrors,\n\t\t\t\tresetKey = 0,\n\t\t\t\tonSubmit,\n\t\t\t\tonCancel,\n\t\t\t\teditingComment,\n\t\t\t\treplyingTo,\n\t\t\t\tstrings: stringsProp,\n\t\t\t\tresources: resourcesProp,\n\t\t\t\tonResourceSearch: onResourceSearchProp,\n\t\t\t\tattachments: attachmentsProp,\n\t\t\t\tmaxAttachments: maxAttachmentsProp,\n\t\t\t\tallowAttachments: allowAttachmentsProp,\n\t\t\t\tinitialValues,\n\t\t\t\tautoFocus = false,\n\t\t\t\tinlineSubmit = true,\n\t\t\t\tplaceholder,\n\t\t},\n\t\tref,\n) {\n\t\tconst strings = useResolvedStrings(stringsProp);\n\t\tconst resources = resourcesProp;\n\t\tconst onResourceSearch = onResourceSearchProp;\n\t\tconst allowAttachments = allowAttachmentsProp ?? true;\n\t\tconst maxAttachments =\n\t\t\t\tattachmentsProp?.maxFiles ??\n\t\t\t\tmaxAttachmentsProp ??\n\t\t\t\t5;\n\t\tconst attachmentsConfig = useMemo(\n\t\t\t\t() => ({\n\t\t\t\t\t\t...attachmentsProp,\n\t\t\t\t\t\tmaxFiles: maxAttachments,\n\t\t\t\t\t\tdisabled: attachmentsProp?.disabled === true || !allowAttachments,\n\t\t\t\t}),\n\t\t\t\t[allowAttachments, attachmentsProp, maxAttachments],\n\t\t);\n\n\t\tconst editorRef = useRef<RichTextEditorHandle>(null);\n\t\tconst [body, setBody] = useState<string>(\n\t\t\t\t() => initialValues?.content ?? editingComment?.content ?? '',\n\t\t);\n\t\tconst [contentError, setContentError] = useState<string | null>(null);\n\t\tconst [attachmentError, setAttachmentError] = useState<string | null>(null);\n\n\t\t/**\n\t\t * Mentions state — picker + caret-trigger detection. The hook reads\n\t\t * the editor handle via the ref we pass; on suggestion select it\n\t\t * inserts the chip and replaces the trigger range automatically.\n\t\t */\n\t\tconst mentions = useMentions({\n\t\t\t\tresources,\n\t\t\t\tonResourceSearch,\n\t\t\t\teditorRef,\n\t\t\t\tinitialMentions:\n\t\t\t\t\t\tinitialValues?.references ?? editingComment?.references,\n\t\t});\n\n\t\tconst attachmentUpload = useAttachmentUpload({\n\t\t\t\t...attachmentsConfig,\n\t\t\t\tinitialAttachments: initialValues?.attachments ?? undefined,\n\t\t\t\tstrings,\n\t\t\t\tonError: setAttachmentError,\n\t\t});\n\t\tconst handleCancel = () => {\n\t\t\t\tattachmentUpload.reset();\n\t\t\t\tsetAttachmentError(null);\n\t\t\t\tonCancel?.();\n\t\t};\n\n\t\tuseImperativeHandle(\n\t\t\t\tref,\n\t\t\t\t() => ({\n\t\t\t\t\t\tfocus: () => editorRef.current?.focus(),\n\t\t\t\t\t\tclear: () => {\n\t\t\t\t\t\t\t\teditorRef.current?.clear();\n\t\t\t\t\t\t\t\tmentions.reset();\n\t\t\t\t\t\t\t\tattachmentUpload.reset();\n\t\t\t\t\t\t\t\tsetContentError(null);\n\t\t\t\t\t\t\t\tsetAttachmentError(null);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsetBody: (html) => {\n\t\t\t\t\t\t\t\teditorRef.current?.setHTML(html);\n\t\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\t[attachmentUpload, mentions],\n\t\t);\n\n\t\t// Reset on context change / resetKey bump\n\t\tuseEffect(() => {\n\t\t\t\teditorRef.current?.setHTML(initialValues?.content ?? '');\n\t\t\t\tmentions.setMentions(initialValues?.references ?? []);\n\t\t\t\tattachmentUpload.reset();\n\t\t\t\tattachmentUpload.setAttachments(initialValues?.attachments ?? []);\n\t\t\t\tsetContentError(null);\n\t\t\t\tsetAttachmentError(null);\n\t\t\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t\t}, [context.id, context.type, resetKey]);\n\n\t\t// Sync editing comment payload\n\t\tuseEffect(() => {\n\t\t\t\tif (!editingComment) return;\n\t\t\t\teditorRef.current?.setHTML(editingComment.content ?? '');\n\t\t\t\tmentions.setMentions(editingComment.references ?? []);\n\t\t\t\tconst list = (editingComment.attachments ?? []).filter(\n\t\t\t\t\t\t(a): a is NonNullable<typeof a> => !!a,\n\t\t\t\t);\n\t\t\t\tattachmentUpload.reset();\n\t\t\t\tattachmentUpload.setAttachments(list);\n\t\t\t\tsetAttachmentError(null);\n\t\t\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t\t}, [editingComment?.id]);\n\n\t\t// Surface server-side errors\n\t\tuseEffect(() => {\n\t\t\t\tif (errors?.content) {\n\t\t\t\t\t\tsetContentError(errors.content);\n\t\t\t\t}\n\t\t}, [errors]);\n\n\t\tconst handleSubmit = (event?: React.FormEvent) => {\n\t\t\t\tevent?.preventDefault();\n\t\t\t\tif (submitting || attachmentUpload.isUploading) return;\n\t\t\t\tconst html = editorRef.current?.getHTML() ?? body;\n\t\t\t\tif (!hasMeaningfulContent(html)) {\n\t\t\t\t\t\tsetContentError(strings.invalidContent);\n\t\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsetContentError(null);\n\n\t\t\t\tconst values: CommentFormValues = {\n\t\t\t\t\t\tcontent: html,\n\t\t\t\t\t\tcommentableId: context.id,\n\t\t\t\t\t\tcommentableType: context.type,\n\t\t\t\t\t\tmoduleKey: context.moduleKey,\n\t\t\t\t\t\tcontentType: 'html',\n\t\t\t\t\t\treferences: mentions.mentions,\n\t\t\t\t\t\tattachments: attachmentUpload.uploadedAttachments,\n\t\t\t\t\t\treplyToId: replyingTo?.commentId ?? initialValues?.replyToId,\n\t\t\t\t\t\teditingId: editingComment?.id,\n\t\t\t\t};\n\n\t\t\t\tonSubmit(values);\n\t\t};\n\n\t\tconst fileInputRef = useRef<HTMLInputElement>(null);\n\t\tconst handleAttachmentClick = () => fileInputRef.current?.click();\n\t\tconst handleFiles = (files: FileList | null) => {\n\t\t\t\tif (!files?.length) return;\n\t\t\t\tsetAttachmentError(null);\n\t\t\t\tattachmentUpload.addFiles(files);\n\t\t};\n\n\t\tconst hasAttachments = attachmentUpload.attachments.length > 0;\n\t\tconst isEditing = !!editingComment;\n\t\tconst isReplying = !isEditing && !!replyingTo;\n\n\t\tconst submitLabel = submitting\n\t\t\t\t? strings.composerSubmitting\n\t\t\t\t: isEditing\n\t\t\t\t\t? strings.composerSave\n\t\t\t\t\t: strings.composerSubmit;\n\n\t\tconst eyebrow: ReactNode = isEditing ? (\n\t\t\t\t<ComposerEyebrow\n\t\t\t\t\t\tlabel={strings.composerEditingEyebrow}\n\t\t\t\t\t\tcloseLabel={strings.composerCancel}\n\t\t\t\t\t\tonClose={onCancel ? handleCancel : undefined}\n\t\t\t\t/>\n\t\t) : isReplying ? (\n\t\t\t\t<ComposerEyebrow\n\t\t\t\t\t\tlabel={makeReplyEyebrow(\n\t\t\t\t\t\t\t\tstrings.composerReplyingEyebrow,\n\t\t\t\t\t\t\t\treplyingTo.authorName,\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tcloseLabel={strings.composerCancel}\n\t\t\t\t\t\tonClose={onCancel ? handleCancel : undefined}\n\t\t\t\t/>\n\t\t) : null;\n\n\t\tconst extraToolbarItems = useMemo<ReadonlyArray<RichTextEditorToolbarItem>>(() => {\n\t\t\t\tconst items: RichTextEditorToolbarItem[] = [];\n\t\t\t\tif (resources && Object.keys(resources).length > 0) {\n\t\t\t\t\t\titems.push({\n\t\t\t\t\t\t\t\tid: 'reference',\n\t\t\t\t\t\t\t\ticon: AtSign,\n\t\t\t\t\t\t\t\tlabel: strings.composerReferenceLabel,\n\t\t\t\t\t\t\t\tonClick: () => mentions.setPickerOpen(true),\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (attachmentsConfig?.onUpload && !attachmentsConfig.disabled) {\n\t\t\t\t\t\titems.push({\n\t\t\t\t\t\t\t\tid: 'attachment',\n\t\t\t\t\t\t\t\ticon: Paperclip,\n\t\t\t\t\t\t\t\tlabel: strings.composerAttachmentLabel,\n\t\t\t\t\t\t\t\tonClick: handleAttachmentClick,\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn items;\n\t\t\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t\t}, [\n\t\t\t\tresources,\n\t\t\t\tattachmentsConfig?.onUpload,\n\t\t\t\tattachmentsConfig?.disabled,\n\t\t\t\tstrings.composerReferenceLabel,\n\t\t\t\tstrings.composerAttachmentLabel,\n\t\t]);\n\n\t\tif (!canComment) return null;\n\n\t\tconst submitButton = (\n\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={() => handleSubmit()}\n\t\t\t\t\t\tdisabled={submitting || attachmentUpload.isUploading}\n\t\t\t\t\t\ticon={submitting ? Loader2 : Send}\n\t\t\t\t>\n\t\t\t\t\t\t{submitLabel}\n\t\t\t\t</Button>\n\t\t);\n\n\t\tconst cancelButton = (isEditing || isReplying || onCancel) ? (\n\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\tonClick={handleCancel}\n\t\t\t\t\t\tdisabled={submitting}\n\t\t\t\t>\n\t\t\t\t\t\t{strings.composerCancel}\n\t\t\t\t</Button>\n\t\t) : null;\n\n\t\t// Mentions live as inline `<span class=\"rsc-mention\" contenteditable=\"false\">`\n\t\t// chips inside the editor body — they're visible, dismissible (single\n\t\t// backspace deletes the whole span), and the HTML→mentions sync keeps\n\t\t// `mentions.mentions` aligned automatically. Rendering them again as a\n\t\t// chip-list below the editor was redundant and confusing.\n\n\t\tconst attachmentChips = hasAttachments ? (\n\t\t\t\t<Stack direction=\"horizontal\" wrap align=\"center\" gap=\"sm\">\n\t\t\t\t\t\t{attachmentUpload.attachments.map((attachment) => (\n\t\t\t\t\t\t\t\t<CommentAttachmentChip\n\t\t\t\t\t\t\t\t\t\tkey={attachment.id}\n\t\t\t\t\t\t\t\t\t\tattachment={attachment}\n\t\t\t\t\t\t\t\t\t\teditable\n\t\t\t\t\t\t\t\t\t\tonRemove={(id) => { setAttachmentError(null); attachmentUpload.removeAttachment(id); }}\n\t\t\t\t\t\t\t\t\t\tonRetry={(id) => { setAttachmentError(null); attachmentUpload.retryAttachment(id); }}\n\t\t\t\t\t\t\t\t\t\tstrings={stringsProp}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t</Stack>\n\t\t) : null;\n\n\t\tconst footerSlot = hasAttachments ? attachmentChips : null;\n\n\t\tconst trailingSubmit =\n\t\t\t\tinlineSubmit !== false && !isEditing && !isReplying\n\t\t\t\t\t\t? submitButton\n\t\t\t\t\t\t: null;\n\t\tconst showFooterRow = inlineSubmit === false || isEditing || isReplying;\n\n\t\treturn (\n\t\t<Stack render={<form />} gap=\"md\" onSubmit={handleSubmit} className=\"comment-composer--component\">\n\t\t\t\t\t\t{eyebrow}\n\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\tref={fileInputRef}\n\t\t\t\t\t\t\t\ttype=\"file\"\n\t\t\t\t\t\t\t\tmultiple\n\t\t\t\t\t\t\t\thidden\n\t\t\t\t\t\t\t\taccept={attachmentsConfig?.accept}\n\t\t\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\t\t\t\thandleFiles(e.target.files);\n\t\t\t\t\t\t\t\t\t\te.target.value = '';\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t{/* Manual button-click flow: regular popover anchored to the\n\t\t\t\t\t\t\t\thidden trigger. The inline-trigger flow uses the panel\n\t\t\t\t\t\t\t\trendered below — no focus stealing while the user types. */}\n\t\t\t\t\t\t{!mentions.triggerActive && (\n\t\t\t\t\t\t\t\t<Popover open={mentions.pickerOpen} onOpenChange={mentions.setPickerOpen}>\n\t\t\t\t\t\t\t\t\t\t<PopoverTrigger\n\t\t\t\t\t\t\t\t\t\t\t\trender={\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"sr-only\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttabIndex={-1}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{strings.composerReferenceLabel}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t<MentionPicker\n\t\t\t\t\t\t\t\t\t\t\t\topen={mentions.pickerOpen}\n\t\t\t\t\t\t\t\t\t\t\t\tactiveKind={mentions.activeKind}\n\t\t\t\t\t\t\t\t\t\t\t\tsetActiveKind={(kind) => { mentions.setActiveKind(kind); mentions.setManualKindOverride(true); }}\n\t\t\t\t\t\t\t\t\t\t\t\tkinds={mentions.kinds}\n\t\t\t\t\t\t\t\t\t\t\t\tresources={resources}\n\t\t\t\t\t\t\t\t\t\t\t\tquery={mentions.query}\n\t\t\t\t\t\t\t\t\t\t\t\tsetQuery={mentions.setQuery}\n\t\t\t\t\t\t\t\t\t\t\t\tsuggestions={mentions.suggestions}\n\t\t\t\t\t\t\t\t\t\t\t\tloading={mentions.isLoading}\n\t\t\t\t\t\t\t\t\t\t\t\tonSelect={mentions.pickSuggestion}\n\t\t\t\t\t\t\t\t\t\t\t\tstrings={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle: strings.composerReferenceMenuTitle,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsearchPlaceholder: strings.composerReferenceSearchPlaceholder,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tempty: strings.composerReferenceEmpty,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tloading: strings.composerReferenceLoading,\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</Popover>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t<div className=\"comment-composer--editor relative\">\n\t\t\t\t\t\t\t\t<RichTextEditor\n\t\t\t\t\t\t\t\t\t\tref={editorRef}\n\t\t\t\t\t\t\t\t\t\tvalue={body}\n\t\t\t\t\t\t\t\t\t\tonValueChange={(html) => {\n\t\t\t\t\t\t\t\t\t\t\t\tsetBody(html);\n\t\t\t\t\t\t\t\t\t\t\t\t// Sync the draft's mentions list with what's\n\t\t\t\t\t\t\t\t\t\t\t\t// actually present in the HTML — when the user\n\t\t\t\t\t\t\t\t\t\t\t\t// backspaces a chip span out of the body, the\n\t\t\t\t\t\t\t\t\t\t\t\t// chip-list below shrinks too. We merge with\n\t\t\t\t\t\t\t\t\t\t\t\t// the previously-known list so consumer-supplied\n\t\t\t\t\t\t\t\t\t\t\t\t// `href` / `data` payloads survive parsing.\n\t\t\t\t\t\t\t\t\t\t\t\tconst parsed = parseMentionsFromHtml<string>(html);\n\t\t\t\t\t\t\t\t\t\t\t\tconst previous = mentions.mentions;\n\t\t\t\t\t\t\t\t\t\t\t\tconst previousIds = previous.map((m) => m.id).join('|');\n\t\t\t\t\t\t\t\t\t\t\t\tconst currentIds = parsed.map((m) => m.id).join('|');\n\t\t\t\t\t\t\t\t\t\t\t\tif (previousIds !== currentIds) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst byId = new Map(previous.map((m) => [m.id, m]));\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconst merged = parsed.map(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(p) => byId.get(p.id) ?? p,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmentions.setMentions(merged);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\tplaceholder={placeholder ?? strings.composerPlaceholder}\n\t\t\t\t\t\t\t\t\t\tstrings={{\n\t\t\t\t\t\t\t\t\t\t\t\teditorLabel: placeholder ?? strings.composerPlaceholder,\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\tminHeight=\"3rem\"\n\t\t\t\t\t\t\t\t\t\tautoFocus={autoFocus || isEditing || isReplying}\n\t\t\t\t\t\t\t\t\t\textraToolbarItems={extraToolbarItems}\n\t\t\t\t\t\t\t\t\t\ttoolbarTrailing={trailingSubmit}\n\t\t\t\t\t\t\t\t\t\tfooterSlot={footerSlot}\n\t\t\t\t\t\t\t\t\t\tonCaretChange={mentions.handleCaretChange}\n\t\t\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t\t\t<MentionInlineSuggestions\n\t\t\t\t\t\t\t\t\t\topen={mentions.triggerActive && mentions.pickerOpen}\n\t\t\t\t\t\t\t\t\t\tactiveKind={mentions.activeKind}\n\t\t\t\t\t\t\t\t\t\tsetActiveKind={(kind) => { mentions.setActiveKind(kind); mentions.setManualKindOverride(true); }}\n\t\t\t\t\t\t\t\t\t\tkinds={mentions.kinds}\n\t\t\t\t\t\t\t\t\t\tresources={resources}\n\t\t\t\t\t\t\t\t\t\tquery={mentions.query}\n\t\t\t\t\t\t\t\t\t\tsuggestions={mentions.suggestions}\n\t\t\t\t\t\t\t\t\t\tsuggestionsByKind={mentions.suggestionsByKind}\n\t\t\t\t\t\t\t\t\t\tloading={mentions.isLoading}\n\t\t\t\t\t\t\t\t\t\tonSelect={mentions.pickSuggestion}\n\t\t\t\t\t\t\t\t\t\tstrings={{\n\t\t\t\t\t\t\t\t\t\t\t\ttitle: strings.composerReferenceMenuTitle,\n\t\t\t\t\t\t\t\t\t\t\t\tempty: strings.composerReferenceEmpty,\n\t\t\t\t\t\t\t\t\t\t\t\tloading: strings.composerReferenceLoading,\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t{attachmentError && (\n\t\t\t\t\t\t\t\t<Text role=\"alert\" size=\"xs\" type=\"error\" className=\"comment-composer--attachment-error\">\n\t\t\t\t\t\t\t\t\t\t{attachmentError}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{contentError && (\n\t\t\t\t\t\t\t\t<Text size=\"xs\" type=\"error\">\n\t\t\t\t\t\t\t\t\t\t{contentError}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{showFooterRow && (\n\t\t\t\t\t\t\t\t<Stack direction=\"horizontal\" align=\"center\" justify=\"end\" gap=\"md\" className=\"comment-composer--footer-actions\">\n\t\t\t\t\t\t\t\t\t\t{cancelButton}\n\t\t\t\t\t\t\t\t\t\t{submitButton}\n\t\t\t\t\t\t\t\t</Stack>\n\t\t\t\t\t\t)}\n\t\t</Stack>\n\t\t);\n});\n\n/** Preserve the consumer's resource-kind union through the forwarded-ref boundary. */\nexport const CommentComposer = CommentComposerBase as <\n\t\tTResource extends string = string,\n>(\n\t\tprops: CommentComposerProps<TResource> & RefAttributes<CommentComposerHandle>,\n) => ReactElement | null;\n\n/* ------------------------------------------------------------------ */\n/* ComposerEyebrow */\n/* ------------------------------------------------------------------ */\n\nfunction ComposerEyebrow({\n\t\tlabel,\n\t\tcloseLabel,\n\t\tonClose,\n}: {\n\t\tlabel: string;\n\t\tcloseLabel: string;\n\t\tonClose?: () => void;\n}) {\n\t\treturn (\n\t\t\t\t<div className={cn('comment-composer--eyebrow bg-muted/40 ring-border/60 flex min-w-0 items-center justify-between gap-space-sm rounded-radius px-row-x ring-1 ring-inset', rowBlockPaddingClasses.compact)}>\n\t\t\t\t\t\t<DisplayLabel>\n\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t</DisplayLabel>\n\t\t\t\t\t\t{onClose ? (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tonClick={onClose}\n\t\t\t\t\t\t\t\t\t\tclassName={cn(fieldAffordanceRecipes.target, fieldAffordanceRecipes.focus, fieldAffordanceRecipes.toggle)}\n\t\t\t\t\t\t\t\t\t\taria-label={closeLabel}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<X className={fieldAffordanceRecipes.icon} aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t);\n}\n\n/** Helper export for templated reply eyebrow. */\nexport function makeReplyEyebrow(template: string, name?: string): string {\n\t\treturn interpolateString(template, { name }, { missing: 'empty' });\n}\n","/**\n * CommentEmpty — default empty state for the timeline. Replaceable via\n * the `emptySlot` prop on `<Comments>` / `<CommentTimeline>`.\n */\nimport { MessageCircle } from 'lucide-react';\nimport type { FC, ReactNode } from 'react';\n\nimport { EmptyState } from '../../../blocks/data-display';\nimport type { StringsProp } from '../../../../lib/strings';\nimport { cn } from '../../../../lib/utils';\n\nimport { useResolvedStrings } from '../comments-provider';\nimport type { CommentsStrings } from '../comments.strings';\n\nexport interface CommentEmptyProps {\n\t/** Overrides this surface's own copy. */\n\tstrings?: StringsProp<CommentsStrings>;\n\t/** Leading glyph. */\n\ticon?: ReactNode;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n}\n\nexport const CommentEmpty: FC<CommentEmptyProps> = ({\n\tstrings: stringsProp,\n\ticon,\n\tclassName,\n}) => {\n\tconst strings = useResolvedStrings(stringsProp);\n\n\treturn (\n\t\t<EmptyState\n\t\t\ttitle={strings.empty}\n\t\t\tdescription={strings.emptyHint || false}\n\t\t\tmedia={icon ?? <MessageCircle className=\"size-icon\" aria-hidden=\"true\" />}\n\t\t\tmediaVariant=\"icon-soft\"\n\t\t\tpadding=\"md\"\n\t\t\tclassName={cn('comment-empty--component', className)}\n\t\t/>\n\t);\n};\n","import type { ReactNode } from 'react';\nimport { Fragment, createElement } from 'react';\n\nimport { Text } from '../../../typography';\nimport { sanitizeHtml } from '../../../../lib/sanitize-html';\nimport { contentTypographyClassName } from '../../../typography/content-typography';\n\nimport { RichText } from '../../../typography/rich-text';\nimport { MentionContent } from '../../mentions';\n\nimport type {\n\tCommentData,\n\tCommentUser,\n\tCommentsConfig,\n\tCommentsSlots,\n} from '../comments.types';\n\nexport interface CommentContentProps<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n> {\n\t/** The comment to render. */\n\tcomment: CommentData<TUser, TMeta, TResource>;\n\t/** Resource registry — passed through to `<MentionContent>`. */\n\tresources?: CommentsConfig<TUser, TMeta, TResource>['resources'];\n\t/** Replaces the default rendering of an inline reference. */\n\trenderReference?: CommentsSlots<\n\t\tTUser,\n\t\tTMeta,\n\t\tTResource\n\t>['renderReference'];\n\t/** Optional sanitizer override. The package safe allowlist is the default. */\n\tsanitizer?: (html: string) => string;\n}\n\nexport function CommentContent<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n>(\n\tprops: CommentContentProps<TUser, TMeta, TResource>,\n): ReactNode {\n\tconst { comment, resources, renderReference, sanitizer } = props;\n\tconst contentType =\n\t\tcomment.contentType ??\n\t\t(comment as Record<string, unknown>).content_type ??\n\t\t'text';\n\n\tif (contentType === 'rich') {\n\t\tconst richContent = renderRichContent(comment.content);\n\t\treturn richContent ? (\n\t\t\t<div className=\"comment-content--component\">{richContent}</div>\n\t\t) : null;\n\t}\n\n\tif (contentType === 'html') {\n\t\treturn (\n\t\t\t<div className=\"comment-content--component\">\n\t\t\t\t<MentionContent<TResource>\n\t\t\t\t\thtml={comment.content ?? ''}\n\t\t\t\t\tmentions={comment.references}\n\t\t\t\t\tresources={resources}\n\t\t\t\t\trenderMention={renderReference}\n\t\t\t\t\tsanitizer={sanitizer}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t}\n\n\tconst plainContent = decodeQuotedString(comment.content ?? '');\n\n\treturn (\n\t\t<Text className=\"comment-content--component whitespace-pre-line\">\n\t\t\t{plainContent}\n\t\t</Text>\n\t);\n}\n\n/* ------------------------------------------------------------------ */\n/* Rich-block renderer for Editor.js-style structured content */\n/* ------------------------------------------------------------------ */\n\nfunction renderRichContent(rawContent: string | null | undefined): ReactNode {\n\tif (!rawContent) return null;\n\n\ttry {\n\t\tconst parsed = JSON.parse(rawContent) as {\n\t\t\tblocks?: Array<{ id?: string; type: string; data?: Record<string, unknown> }>;\n\t\t};\n\n\t\tif (!parsed || !Array.isArray(parsed.blocks) || parsed.blocks.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn (\n\t\t\t<Text tag=\"div\" className={contentTypographyClassName}>\n\t\t\t\t{parsed.blocks.map((block, index) => (\n\t\t\t\t\t<Fragment key={block.id ?? `${block.type}-${index}`}>\n\t\t\t\t\t\t{renderRichBlock(block)}\n\t\t\t\t\t</Fragment>\n\t\t\t\t))}\n\t\t\t</Text>\n\t\t);\n\t} catch {\n\t\tconst decoded = decodeQuotedString(rawContent);\n\t\treturn (\n\t\t\t<Text className=\"whitespace-pre-line\">\n\t\t\t\t{decoded}\n\t\t\t</Text>\n\t\t);\n\t}\n}\n\nfunction renderRichBlock(block: { type: string; data?: Record<string, unknown> }): ReactNode {\n\tconst data = block.data ?? {};\n\n\tswitch (block.type) {\n\t\tcase 'paragraph': {\n\t\t\tconst raw = String(data.text ?? '').trim();\n\t\t\tif (!raw) return null;\n\t\t\tconst html = sanitizeHtml(raw);\n\t\t\treturn html ? <p dangerouslySetInnerHTML={{ __html: html }} /> : null;\n\t\t}\n\t\tcase 'header': {\n\t\t\tconst text = stripHtml(String(data.text ?? ''));\n\t\t\tconst level = Number(data.level ?? 3);\n\t\t\tif (!text) return null;\n\t\t\tconst safeLevel = Math.min(Math.max(level, 1), 6);\n\t\t\treturn createElement(\n\t\t\t\t`h${safeLevel}`,\n\t\t\t\tnull,\n\t\t\t\ttext,\n\t\t\t);\n\t\t}\n\t\tcase 'list': {\n\t\t\tconst items = Array.isArray(data.items) ? data.items : [];\n\t\t\tconst sanitizedItems = items\n\t\t\t\t.map((item) => stripHtml(String(item ?? '')))\n\t\t\t\t.filter((item) => item.length > 0);\n\n\t\t\tif (sanitizedItems.length === 0) return null;\n\n\t\t\tif (data.style === 'ordered') {\n\t\t\t\treturn (\n\t\t\t\t\t<ol>\n\t\t\t\t\t\t{sanitizedItems.map((item, index) => (\n\t\t\t\t\t\t\t<li key={`${item}-${index}`}>\n\t\t\t\t\t\t\t\t<Text tag=\"span\">{item}</Text>\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ol>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\t<ul>\n\t\t\t\t\t{sanitizedItems.map((item) => (\n\t\t\t\t\t\t<li key={item}>\n\t\t\t\t\t\t\t<Text tag=\"span\">{item}</Text>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t);\n\t\t}\n\t\tcase 'quote': {\n\t\t\tconst text = String(data.text ?? '').trim();\n\t\t\tif (!text) return null;\n\t\t\tconst caption = stripHtml(String(data.caption ?? ''));\n\t\t\treturn (\n\t\t\t\t<blockquote className=\"italic\">\n\t\t\t\t\t<RichText tag=\"div\" html={text} type=\"secondary\" />\n\t\t\t\t\t{caption.length > 0 && (\n\t\t\t\t\t\t<cite className=\"mt-1 block not-italic\">\n\t\t\t\t\t\t\t<Text tag=\"span\" size=\"xs\" type=\"secondary\" className=\"opacity-80\">\n\t\t\t\t\t\t\t\t— {caption}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t</cite>\n\t\t\t\t\t)}\n\t\t\t\t</blockquote>\n\t\t\t);\n\t\t}\n\t\tcase 'delimiter':\n\t\t\treturn (\n\t\t\t\t<hr\n\t\t\t\t\tclassName=\"border-dashed\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t/>\n\t\t\t);\n\t\tdefault: {\n\t\t\tconst text = stripHtml(String(data.text ?? ''));\n\t\t\tif (!text) return null;\n\t\t\treturn <p className=\"whitespace-pre-line\">{text}</p>;\n\t\t}\n\t}\n}\n\nfunction stripHtml(value: string): string {\n\treturn value.replace(/<[^>]*>/g, '').trim();\n}\n\nfunction decodeQuotedString(value: string | null | undefined): string {\n\tif (typeof value !== 'string') return '';\n\tconst trimmed = value.trim();\n\tif (trimmed === '') return '';\n\tif (trimmed.startsWith('{') || trimmed.startsWith('[')) return trimmed;\n\ttry {\n\t\tconst parsed = JSON.parse(trimmed);\n\t\tif (typeof parsed === 'string') return parsed;\n\t} catch {\n\t\t// ignore\n\t}\n\tif (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n\t\treturn trimmed.slice(1, -1);\n\t}\n\treturn trimmed;\n}\n","import {\n\tCornerDownRight,\n\tPencil,\n\tPin,\n\tSmile,\n\tTrash2,\n} from 'lucide-react';\nimport type { FC } from 'react';\nimport { memo, useCallback, useMemo, useState } from 'react';\n\nimport {\n\tAvatar,\n\tAvatarFallback,\n\tAvatarImage,\n} from '../../../base/avatar';\nimport { Badge } from '../../../base/badge';\nimport { Button } from '../../../base/buttons';\nimport { ConfirmDialog, useOverlayVisibility } from '../../overlays';\nimport {\n\tTooltip,\n\tTooltipContent,\n\tTooltipProvider,\n\tTooltipTrigger,\n} from '../../../base/display/tooltip';\nimport { Number as NumberValue, RelativeTime } from '../../../primitives';\nimport { Text } from '../../../typography';\nimport { Stack } from '../../../base/structure';\nimport { cn } from '../../../../lib/utils';\nimport { fieldAffordanceRecipes } from '../../../../lib/field-affordance-recipes';\nimport { interpolateString } from '../../../../lib/strings';\nimport { defaultCommentsStrings } from '../comments.strings';\n\nimport {\n\tuseResolvedAccessors,\n\tuseResolvedStrings,\n} from '../comments-provider';\nimport type {\n\tCommentAttachment,\n\tCommentItemProps,\n\tCommentUser,\n} from '../comments.types';\nimport { CommentAttachmentChip } from './comment-attachment-chip';\nimport { CommentContent } from './comment-content';\n\nconst FALLBACK_INITIAL = '?';\n\nconst defaultGetMediaUrl = (m: CommentAttachment | null | undefined) => m?.url;\nconst defaultGetMediaName = (m: CommentAttachment | null | undefined) => m?.name;\nconst defaultGetStatusLabel = (s: string) =>\n\ts.charAt(0).toUpperCase() + s.slice(1).replace(/_/g, ' ');\n\nexport const CommentItem = memo(function CommentItem<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n>({\n\tcomment,\n\tcanModerate,\n\tonDelete,\n\tonAttachmentRemove,\n\tonEdit,\n\tonPinToggle,\n\tonReact,\n\tonReply,\n\tallowReactions: allowReactionsProp,\n\tallowReplies: allowRepliesProp,\n\tsanitizer,\n\tstrings: stringsProp,\n\tgetMediaUrl,\n\tgetMediaName,\n\tgetStatusLabel,\n\tformatRelativeTime,\n\tresources,\n\trenderAttachment,\n\trenderReference,\n}: CommentItemProps<TUser, TMeta, TResource>) {\n\tconst strings = useResolvedStrings(stringsProp);\n\tconst allowReactions = allowReactionsProp ?? true;\n\tconst allowReplies = allowRepliesProp ?? true;\n\tconst accessors = useResolvedAccessors({\n\t\tgetMediaUrl,\n\t\tgetMediaName,\n\t\tgetStatusLabel,\n\t\tformatRelativeTime,\n\t});\n\n\tconst resolvedGetMediaUrl = accessors.getMediaUrl ?? defaultGetMediaUrl;\n\tconst resolvedGetMediaName = accessors.getMediaName ?? defaultGetMediaName;\n\tconst resolvedGetStatusLabel =\n\t\taccessors.getStatusLabel ?? defaultGetStatusLabel;\n\tconst resolvedFormatRelativeTime = accessors.formatRelativeTime;\n\n\tconst authorName = comment.user?.name ?? strings.fallbackAuthor;\n\tconst avatarUrl = comment.user?.avatar ?? undefined;\n\n\tconst fallbackInitial = useMemo(() => {\n\t\tif (!authorName) return FALLBACK_INITIAL;\n\t\tconst trimmed = authorName.trim();\n\t\treturn trimmed === ''\n\t\t\t? FALLBACK_INITIAL\n\t\t\t: trimmed.charAt(0).toUpperCase();\n\t}, [authorName]);\n\n\tconst tagList = useMemo(() => {\n\t\tif (Array.isArray(comment.tagsArray)) {\n\t\t\treturn comment.tagsArray.filter(\n\t\t\t\t(tag): tag is string => typeof tag === 'string',\n\t\t\t);\n\t\t}\n\t\tif (comment.tagsArray && typeof comment.tagsArray === 'object') {\n\t\t\treturn Object.values(comment.tagsArray).filter(\n\t\t\t\t(value): value is string => typeof value === 'string',\n\t\t\t);\n\t\t}\n\t\treturn [];\n\t}, [comment.tagsArray]);\n\n\tconst attachments = useMemo(() => {\n\t\tconst list = comment.attachments ?? [];\n\t\treturn list.filter(\n\t\t\t(a): a is CommentAttachment => !!a && typeof a === 'object',\n\t\t);\n\t}, [comment.attachments]);\n\n\tconst reactions = allowReactions ? (comment.reactions ?? []) : [];\n\n\tconst isPinned = comment.isPinned === true;\n\tconst isEdited = comment.isEdited === true;\n\tconst showStatus = comment.status && comment.status !== 'active';\n\tconst statusLabel =\n\t\tshowStatus && comment.status ? resolvedGetStatusLabel(comment.status) : null;\n\tconst canDeleteComment =\n\t\tcomment.canDelete === true || canModerate === true;\n\tconst canEditComment = comment.canEdit === true || canModerate === true;\n\tconst canReply = !!allowReplies && !!onReply && !!comment.id;\n\tconst canReact = !!allowReactions && !!onReact && !!comment.id;\n\tconst canPin = !!onPinToggle && !!canModerate;\n\tconst canEdit = !!canEditComment && !!onEdit && !!comment.id;\n\tconst canDelete = !!canDeleteComment && !!onDelete && !!comment.id;\n\tconst hasActions = canReply || canReact || canPin || canEdit || canDelete;\n\n\tconst attachmentConfirm = useOverlayVisibility();\n\tconst [pendingAttachmentId, setPendingAttachmentId] = useState<string | null>(null);\n\tconst requestAttachmentRemoval = useCallback(\n\t\t(attachmentId: string) => {\n\t\t\tsetPendingAttachmentId(attachmentId);\n\t\t\tattachmentConfirm.show();\n\t\t},\n\t\t[attachmentConfirm],\n\t);\n\n\tconst hasAttachments = attachments.length > 0;\n\n\treturn (\n\t\t<article\n\t\t\tclassName={cn(\n\t\t\t\t'comment-item--component group relative overflow-hidden rounded-radius border transition-colors',\n\t\t\t\t'border-border/60 bg-card hover:bg-muted/30 p-surface',\n\t\t\t)}\n\t\t\tdata-comment-id={comment.id}\n\t\t>\n\t\t\t<Stack direction=\"horizontal\" align=\"start\" gap=\"lg\" className=\"min-w-0\">\n\t\t\t\t<Avatar className=\"mt-0.5 size-avatar shrink-0\">\n\t\t\t\t\t{!!avatarUrl && (\n\t\t\t\t\t\t<AvatarImage src={avatarUrl} alt={authorName} />\n\t\t\t\t\t)}\n\t\t\t\t\t<AvatarFallback className=\"bg-muted text-muted-foreground text-xs font-medium\">\n\t\t\t\t\t\t{fallbackInitial}\n\t\t\t\t\t</AvatarFallback>\n\t\t\t\t</Avatar>\n\n\t\t\t\t<div className=\"comment-item--body min-w-0 flex-1\">\n\t\t\t\t\t<Stack direction=\"horizontal\" align=\"baseline\" gap=\"md\" className=\"min-w-0\">\n\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\tweight=\"semibold\"\n\t\t\t\t\t\t\tclassName=\"truncate\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{authorName}\n\t\t\t\t\t\t</Text>\n\n\t\t\t\t\t\t{!!isPinned && (\n\t\t\t\t\t\t\t<TooltipProvider delayDuration={0}>\n\t\t\t\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t\t\t\t<TooltipTrigger render={<span className=\"inline-flex shrink-0 self-center\" />}>\n\t\t\t\t\t\t\t\t\t\t<Pin className=\"text-warning-accent size-icon-sm\" aria-hidden />\n\t\t\t\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t\t\t\t<TooltipContent\n\t\t\t\t\t\t\t\t\t\tside=\"top\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"text-xs\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{strings.pinned}\n\t\t\t\t\t\t\t\t\t</TooltipContent>\n\t\t\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t\t\t</TooltipProvider>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t<RelativeTime\n\t\t\t\t\t\t\tvalue={comment.createdAt}\n\t\t\t\t\t\t\tformatRelativeTime={resolvedFormatRelativeTime}\n\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\tclassName=\"shrink-0 tabular-nums\"\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t{!!isEdited && (\n\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\t\ttype=\"secondary\"\n\t\t\t\t\t\t\t\tclassName=\"shrink-0\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{strings.edited}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{!!showStatus && !!statusLabel && (\n\t\t\t\t\t\t\t<Badge size=\"sm\" tone=\"secondary\" className=\"self-center\">\n\t\t\t\t\t\t\t\t{statusLabel}\n\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</Stack>\n\n\t\t\t\t\t<div className=\"mt-1 leading-relaxed\">\n\t\t\t\t\t\t<CommentContent\n\t\t\t\t\t\t\tcomment={comment}\n\t\t\t\t\t\t\tresources={resources}\n\t\t\t\t\t\t\trenderReference={renderReference}\n\t\t\t\t\t\t\tsanitizer={sanitizer}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{tagList.length > 0 && (\n\t\t\t\t\t\t<div className=\"mt-space-md flex flex-wrap gap-space-sm\">\n\t\t\t\t\t\t\t{tagList.map((tag) => (\n\t\t\t\t\t\t\t\t<Badge key={tag} size=\"sm\" tone=\"secondary\">\n\t\t\t\t\t\t\t\t\t{tag}\n\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{hasAttachments && (\n\t\t\t\t\t\t<div className=\"mt-space-md flex flex-wrap gap-space-sm\">\n\t\t\t\t\t\t\t{attachments.map((attachment) => {\n\t\t\t\t\t\t\t\tif (renderAttachment) {\n\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t<div key={attachment.id ?? attachment.name}>\n\t\t\t\t\t\t\t\t\t\t\t{renderAttachment(attachment)}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t * Posted attachments were read-only: no control, no\n\t\t\t\t\t\t\t\t * callback, nothing to remove. The control appears only\n\t\t\t\t\t\t\t\t * when the consumer supplies `onAttachmentRemove` and the\n\t\t\t\t\t\t\t\t * viewer may edit the comment, and detaching a published\n\t\t\t\t\t\t\t\t * file is irreversible, so it asks first.\n\t\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\t\tconst canRemoveAttachment =\n\t\t\t\t\t\t\t\t\t!!onAttachmentRemove && !!attachment.id && canDeleteComment;\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<CommentAttachmentChip\n\t\t\t\t\t\t\t\t\t\tkey={attachment.id ?? attachment.name}\n\t\t\t\t\t\t\t\t\t\tattachment={attachment}\n\t\t\t\t\t\t\t\t\t\teditable={canRemoveAttachment}\n\t\t\t\t\t\t\t\t\t\tonRemove={\n\t\t\t\t\t\t\t\t\t\t\tcanRemoveAttachment\n\t\t\t\t\t\t\t\t\t\t\t\t? () => requestAttachmentRemoval(attachment.id as string)\n\t\t\t\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\taccessors={{\n\t\t\t\t\t\t\t\t\t\t\tgetMediaUrl: resolvedGetMediaUrl,\n\t\t\t\t\t\t\t\t\t\t\tgetMediaName: resolvedGetMediaName,\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\tstrings={stringsProp}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{reactions.length > 0 && (\n\t\t\t\t\t\t<Stack direction=\"horizontal\" wrap align=\"center\" gap=\"xs\" className=\"mt-space-md\">\n\t\t\t\t\t\t\t{reactions.map((reaction) => (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tkey={reaction.emoji}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\taria-label={interpolateString(strings.reactionLabel ?? defaultCommentsStrings.reactionLabel!, { emoji: reaction.emoji, count: reaction.count })}\n\t\t\t\t\t\t\t\t\taria-pressed={reaction.mine ?? false}\n\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\tonReact && comment.id\n\t\t\t\t\t\t\t\t\t\t\t? onReact(comment.id, reaction.emoji)\n\t\t\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\ttitle={reaction.users?.join(', ')}\n\t\t\t\t\t\t\t\t\tclassName={cn(fieldAffordanceRecipes.inline, fieldAffordanceRecipes.focus)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Badge\n\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\ttone={reaction.mine ? 'primary' : 'secondary'}\n\t\t\t\t\t\t\t\t\t\tclassName=\"cursor-pointer transition-colors hover:opacity-90\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"inherit\"\n\t\t\t\t\t\t\t\t\t\t\tlineHeight=\"none\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"text-inherit\"\n\t\t\t\t\t\t\t\t\t\t\taria-hidden\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{reaction.emoji}\n\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t<NumberValue\n\t\t\t\t\t\t\t\t\t\t\tvalue={reaction.count}\n\t\t\t\t\t\t\t\t\t\t\tsize=\"inherit\"\n\t\t\t\t\t\t\t\t\t\t\talign=\"left\"\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"tabular-nums text-current\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</Stack>\n\t\t\t\t\t)}\n\n\t\t\t\t{/* Actions own a separate row so they never reserve message width. */}\n\t\t\t\t{hasActions && <div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'comment-item--actions relative mt-space-md ms-auto w-fit max-w-full flex-wrap opacity-100 transition-opacity',\n\t\t\t\t\t\t'group-hover:opacity-100 focus-within:opacity-100',\n\t\t\t\t\t\t'inline-flex items-center gap-space-2xs rounded-radius bg-card/95 shadow-sm ring-1 ring-border/70',\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{canReply && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\tcomment.id && onReply(comment.id)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttitle={strings.replyLabel}\n\t\t\t\t\t\t\taria-label={strings.replyLabel}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<CornerDownRight className=\"size-icon-md\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{canReact && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\tcomment.id && onReact(comment.id, '👍')\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttitle={strings.addReactionLabel}\n\t\t\t\t\t\t\taria-label={strings.addReactionLabel}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Smile className=\"size-icon-md\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{canPin && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\tonClick={() => onPinToggle(comment)}\n\t\t\t\t\t\t\ttitle={isPinned ? strings.unpinLabel : strings.pinLabel}\n\t\t\t\t\t\t\taria-label={isPinned ? strings.unpinLabel : strings.pinLabel}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Pin\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'size-icon-md',\n\t\t\t\t\t\t\t\t\tisPinned && 'text-warning-accent',\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{canEdit && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\ttitle={strings.editLabel}\n\t\t\t\t\t\t\taria-label={strings.editLabel}\n\t\t\t\t\t\t\tonClick={() => onEdit(comment)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Pencil className=\"size-icon-md\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t\t{canDelete && (\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\t\tclassName=\"hover:bg-destructive/10 hover:text-destructive\"\n\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\tonDelete(comment.id as string)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttitle={strings.deleteLabel}\n\t\t\t\t\t\t\t\taria-label={strings.deleteLabel}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Trash2 className=\"size-icon-md\" />\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t</div>}\n\t\t\t\t</div>\n\t\t\t</Stack>\n\t\t\t{!!onAttachmentRemove && (\n\t\t\t\t<ConfirmDialog\n\t\t\t\t\t{...attachmentConfirm.overlayProps}\n\t\t\t\t\tdestructive\n\t\t\t\t\ttitle={strings.confirmRemoveAttachmentTitle}\n\t\t\t\t\tdescription={strings.confirmRemoveAttachmentDescription}\n\t\t\t\t\tstrings={{ confirm: strings.attachmentRemoveLabel }}\n\t\t\t\t\tonConfirm={() => {\n\t\t\t\t\t\tif (pendingAttachmentId && comment.id) {\n\t\t\t\t\t\t\tvoid onAttachmentRemove(comment.id as string, pendingAttachmentId);\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</article>\n\t);\n}) as <\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n>(\n\tprops: CommentItemProps<TUser, TMeta, TResource>,\n) => ReturnType<FC>;\n","import type { FC } from 'react';\n\nimport { Stack } from '../../../base/structure';\nimport type { CommentTimelineProps, CommentUser } from '../comments.types';\nimport { CommentEmpty } from './comment-empty';\nimport { CommentItem } from './comment-item';\n\nexport const CommentTimeline = function CommentTimeline<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n>({\n\tcomments,\n\tcanModerate,\n\tonDelete,\n\tonAttachmentRemove,\n\tonEdit,\n\tonPinToggle,\n\tonReact,\n\tonReply,\n\tallowReactions,\n\tallowReplies,\n\tsanitizer,\n\tstrings: stringsProp,\n\tgetMediaUrl,\n\tgetMediaName,\n\tgetStatusLabel,\n\tformatRelativeTime,\n\tresources,\n\trenderItem,\n\trenderAttachment,\n\trenderReference,\n\temptySlot,\n}: CommentTimelineProps<TUser, TMeta, TResource>) {\n\tif (!comments.length) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{emptySlot ?? <CommentEmpty strings={stringsProp} />}\n\t\t\t</>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Stack gap=\"sm\" className=\"comment-timeline--component\">\n\t\t\t{comments.map((comment, index) => {\n\t\t\t\tconst defaultItem = (\n\t\t\t\t\t<CommentItem<TUser, TMeta, TResource>\n\t\t\t\t\t\tcomment={comment}\n\t\t\t\t\t\tcanModerate={canModerate}\n\t\t\t\t\t\tonDelete={onDelete}\n\t\t\t\t\t\tonAttachmentRemove={onAttachmentRemove}\n\t\t\t\t\t\tonEdit={onEdit}\n\t\t\t\t\t\tonPinToggle={onPinToggle}\n\t\t\t\t\t\tonReact={onReact}\n\t\t\t\t\t\tonReply={onReply}\n\t\t\t\t\t\tallowReactions={allowReactions}\n\t\t\t\t\t\tallowReplies={allowReplies}\n\t\t\t\t\t\tsanitizer={sanitizer}\n\t\t\t\t\t\tstrings={stringsProp}\n\t\t\t\t\t\tgetMediaUrl={getMediaUrl}\n\t\t\t\t\t\tgetMediaName={getMediaName}\n\t\t\t\t\t\tgetStatusLabel={getStatusLabel}\n\t\t\t\t\t\tformatRelativeTime={formatRelativeTime}\n\t\t\t\t\t\tresources={resources}\n\t\t\t\t\t\trenderAttachment={renderAttachment}\n\t\t\t\t\t\trenderReference={renderReference}\n\t\t\t\t\t/>\n\t\t\t\t);\n\n\t\t\t\tif (renderItem) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div key={comment.id ?? `comment-${index}`}>\n\t\t\t\t\t\t\t{renderItem({\n\t\t\t\t\t\t\t\tcomment,\n\t\t\t\t\t\t\t\tcanModerate: canModerate ?? false,\n\t\t\t\t\t\t\t\tonDelete,\n\t\t\t\t\t\t\t\tonAttachmentRemove,\n\t\t\t\t\t\t\t\tonEdit,\n\t\t\t\t\t\t\t\tdefaultItem,\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn (\n\t\t\t\t\t<div key={comment.id ?? `comment-${index}`}>\n\t\t\t\t\t\t{defaultItem}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t})}\n\t\t</Stack>\n\t);\n} as <\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n>(\n\tprops: CommentTimelineProps<TUser, TMeta, TResource>,\n) => ReturnType<FC>;\n","/**\n * Comments — top-level entry for the Comments feature.\n *\n * Composes the composer + timeline + empty state behind a single API.\n * Generic in `<TUser, TMeta, TResource>` so consumers can type their\n * domain (user shape, custom meta payload, resource-kind union).\n *\n * Per-mount wiring (callbacks, resources, accessors) flows as direct\n * props. Library-wide display defaults (composer position, etc.) come\n * from `<UIProvider>` — see `@/lib/ui-provider`. Slots, render-props,\n * and the headless `useComments()` hook cover the composability\n * spectrum.\n *\n * Wrap the feature in `Card` at the call site when card chrome is desired.\n */\nimport { useCallback, useState } from 'react';\n\nimport { Stack } from '../../base/structure';\nimport { ConfirmDialog, useOverlayVisibility } from '../overlays';\nimport { Text } from '../../typography';\nimport { useCommentsConfig as useCommentsUIDefaults } from '../../../lib/ui-provider';\n\nimport { useResolvedStrings } from './comments-provider';\nimport type { CommentUser, CommentsProps } from './comments.types';\nimport { useComments } from './hooks/use-comments';\nimport { CommentComposer } from './partials/comment-composer';\nimport { CommentEmpty } from './partials/comment-empty';\nimport { CommentTimeline } from './partials/comment-timeline';\n\nimport { cn } from '../../../lib/utils';\nexport function Comments<\n\tTUser extends CommentUser = CommentUser,\n\tTMeta = unknown,\n\tTResource extends string = string,\n>(props: CommentsProps<TUser, TMeta, TResource>) {\n\tconst ui = useCommentsUIDefaults();\n\n\tconst composerPosition =\n\t\tprops.composerPosition ?? ui.composerPosition ?? 'top';\n\tconst maxAttachments = props.maxAttachments ?? 5;\n\tconst allowAttachments = props.allowAttachments ?? true;\n\tconst allowReactions = props.allowReactions ?? true;\n\tconst allowReplies = props.allowReplies ?? true;\n\n\tconst canComment = props.canComment ?? false;\n\tconst canModerate = props.canModerate ?? false;\n\n\tconst onPinToggle = props.onPinToggle;\n\n\tconst resources = props.resources;\n\tconst attachments = props.attachments;\n\n\tconst strings = useResolvedStrings(props.strings);\n\tconst title = props.title === undefined ? strings.title : props.title;\n\n\t/*\n\t * Deleting a comment is irreversible and the trigger is a bare icon button\n\t * next to Edit, so the confirmation is the component's job rather than every\n\t * consumer's. `confirmDelete={false}` opts out for apps that already confirm\n\t * upstream — otherwise they would ask twice.\n\t */\n\tconst confirmDelete = props.confirmDelete ?? true;\n\tconst deleteConfirm = useOverlayVisibility();\n\tconst [pendingDeleteId, setPendingDeleteId] = useState<string | null>(null);\n\n\tconst commentsState = useComments<TUser, TMeta, TResource>({\n\t\tonSubmit: props.onSubmit,\n\t\tonUpdate: props.onUpdate,\n\t\tonDelete: props.onDelete,\n\t\tonAfterMutate: props.onAfterMutate,\n\t\tonError: props.onError,\n\t});\n\n\tconst requestDelete = useCallback(\n\t\t(id: string) => {\n\t\t\tif (!confirmDelete) {\n\t\t\t\tvoid commentsState.deleteComment(id);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsetPendingDeleteId(id);\n\t\t\tdeleteConfirm.show();\n\t\t},\n\t\t[confirmDelete, commentsState, deleteConfirm],\n\t);\n\tconst startReply = commentsState.startReply;\n\tconst comments = props.comments;\n\tconst onReply = props.onReply;\n\n\tconst handleReply = useCallback(\n\t\t(commentId: string) => {\n\t\t\tconst comment = comments.find((item) => item.id === commentId);\n\t\t\tif (comment) startReply(comment);\n\t\t\tonReply?.(commentId);\n\t\t},\n\t\t[comments, onReply, startReply],\n\t);\n\n\tconst editingComment =\n\t\tcommentsState.composerMode.kind === 'editing'\n\t\t\t? commentsState.composerMode.comment\n\t\t\t: undefined;\n\tconst replyingTo =\n\t\tcommentsState.composerMode.kind === 'replying'\n\t\t\t? {\n\t\t\t\t\tcommentId: commentsState.composerMode.commentId,\n\t\t\t\t\tauthorName: commentsState.composerMode.authorName,\n\t\t\t\t}\n\t\t\t: undefined;\n\n\tconst composer = props.composerSlot ?? (\n\t\tcanComment ? (\n\t\t\t<CommentComposer<TResource>\n\t\t\t\tcontext={props.context}\n\t\t\t\tcanComment={canComment}\n\t\t\t\tsubmitting={commentsState.isSubmitting}\n\t\t\t\terrors={commentsState.formErrors}\n\t\t\t\tresetKey={commentsState.resetKey}\n\t\t\t\teditingComment={editingComment}\n\t\t\t\treplyingTo={replyingTo}\n\t\t\t\tonCancel={\n\t\t\t\t\tcommentsState.composerMode.kind === 'idle'\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: commentsState.cancelComposerMode\n\t\t\t\t}\n\t\t\t\tonSubmit={commentsState.submit}\n\t\t\t\tstrings={props.strings}\n\t\t\t\tresources={resources}\n\t\t\t\tonResourceSearch={props.onResourceSearch}\n\t\t\t\tattachments={attachments}\n\t\t\t\tmaxAttachments={maxAttachments}\n\t\t\t\tallowAttachments={allowAttachments}\n\t\t\t/>\n\t\t) : null\n\t);\n\n\tconst timeline = (\n\t\t<CommentTimeline<TUser, TMeta, TResource>\n\t\t\tcomments={props.comments}\n\t\t\tcanModerate={canModerate}\n\t\t\tonDelete={props.onDelete ? requestDelete : undefined}\n\t\t\tonAttachmentRemove={props.onAttachmentRemove}\n\t\t\tonEdit={\n\t\t\t\tcanComment && props.onUpdate\n\t\t\t\t\t? commentsState.startEdit\n\t\t\t\t\t: undefined\n\t\t\t}\n\t\t\tonPinToggle={onPinToggle}\n\t\t\tonReact={props.onReact}\n\t\t\tonReply={canComment && allowReplies ? handleReply : undefined}\n\t\t\tallowReactions={allowReactions}\n\t\t\tallowReplies={allowReplies}\n\t\t\tsanitizer={props.sanitizer}\n\t\t\tstrings={props.strings}\n\t\t\tgetMediaUrl={props.getMediaUrl}\n\t\t\tgetMediaName={props.getMediaName}\n\t\t\tgetStatusLabel={props.getStatusLabel}\n\t\t\tformatRelativeTime={props.formatRelativeTime}\n\t\t\tresources={resources}\n\t\t\trenderItem={props.renderItem}\n\t\t\trenderAttachment={props.renderAttachment}\n\t\t\trenderReference={props.renderReference}\n\t\t\temptySlot={\n\t\t\t\tprops.emptySlot ?? <CommentEmpty strings={props.strings} />\n\t\t\t}\n\t\t/>\n\t);\n\n\tconst composerBlock = composer ? <div>{composer}</div> : null;\n\n\tconst inner = (\n\t\t<Stack gap=\"xl\" className=\"comments--body\">\n\t\t\t{props.headerSlot}\n\t\t\t{composerPosition === 'top' && composerBlock}\n\t\t\t{timeline}\n\t\t\t{composerPosition === 'bottom' && composerBlock}\n\t\t\t{props.footerSlot}\n\t\t</Stack>\n\t);\n\n\tif (props.bare) {\n\t\treturn inner;\n\t}\n\n\tconst ariaLabel = typeof title === 'string' ? title : undefined;\n\n\treturn (\n\t\t<Stack\n\t\t\trender={<section />}\n\t\t\tgap=\"lg\"\n\t\t\tdata-component=\"comments\"\n\t\t\tdata-slot=\"comments\"\n\t\t\tclassName={cn('comments--component', props.className)}\n\t\t\taria-label={ariaLabel}\n\t\t>\n\t\t\t{!!(title !== false && (title || strings.subtitle)) && (\n\t\t\t\t<Stack gap=\"normal\" className=\"comments--header\">\n\t\t\t\t\t{!!title && <Text weight=\"semibold\">{title}</Text>}\n\t\t\t\t\t{!!strings.subtitle && <Text type=\"secondary\">{strings.subtitle}</Text>}\n\t\t\t\t</Stack>\n\t\t\t)}\n\t\t\t{inner}\n\t\t\t{!!(confirmDelete && props.onDelete) && (\n\t\t\t\t<ConfirmDialog\n\t\t\t\t\t{...deleteConfirm.overlayProps}\n\t\t\t\t\tdestructive\n\t\t\t\t\ttitle={strings.confirmDeleteTitle}\n\t\t\t\t\tdescription={strings.confirmDeleteDescription}\n\t\t\t\t\tstrings={{ confirm: strings.confirmDeleteLabel }}\n\t\t\t\t\tonAsyncConfirm={async () => {\n\t\t\t\t\t\tif (pendingDeleteId) await commentsState.deleteComment(pendingDeleteId);\n\t\t\t\t\t}}\n\t\t\t\t\tonError={props.onError}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</Stack>\n\t);\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Private Tailwind recipes; public props and DOM hooks remain owned by the component. */
|
|
2
2
|
export declare const buttonGroupRecipes: {
|
|
3
|
-
readonly root: "inline-flex items-stretch rounded-
|
|
3
|
+
readonly root: "inline-flex items-stretch rounded-inner box-border data-[orientation=vertical]:flex-col [&[data-orientation=horizontal]>:not(:last-child)]:rounded-e-none [&[data-orientation=horizontal]>:not(:first-child)]:rounded-s-none [&[data-orientation=horizontal]>:not(:first-child)]:-ms-px [&[data-orientation=vertical]>:not(:last-child)]:rounded-b-none [&[data-orientation=vertical]>:not(:first-child)]:rounded-t-none [&[data-orientation=vertical]>:not(:first-child)]:-mt-px";
|
|
4
4
|
readonly text: "inline-flex items-center px-control-sm py-0 bg-muted border border-border text-sm text-muted-foreground";
|
|
5
5
|
readonly separator: "bg-border w-px self-stretch";
|
|
6
6
|
};
|
|
@@ -1,23 +1,14 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Shared interaction states and loader anatomy; public variants own geometry. */
|
|
2
2
|
export declare const buttonRecipes: {
|
|
3
|
-
readonly
|
|
4
|
-
readonly
|
|
5
|
-
readonly
|
|
6
|
-
readonly
|
|
7
|
-
readonly
|
|
8
|
-
readonly
|
|
9
|
-
readonly
|
|
3
|
+
readonly solidInteractive: "[&:hover:not(:active):not(:disabled):not([data-disabled]):not([aria-disabled=true])]:brightness-95 [&:active:not(:disabled):not([data-disabled]):not([aria-disabled=true])]:brightness-90";
|
|
4
|
+
readonly neutralInteractive: "[&:hover:not(:active):not(:disabled):not([data-disabled]):not([aria-disabled=true])]:bg-accent [&:active:not(:disabled):not([data-disabled]):not([aria-disabled=true])]:bg-muted";
|
|
5
|
+
readonly secondaryInteractive: "[&:hover:not(:active):not(:disabled):not([data-disabled]):not([aria-disabled=true])]:bg-secondary [&:active:not(:disabled):not([data-disabled]):not([aria-disabled=true])]:bg-accent";
|
|
6
|
+
readonly primaryInteractive: "[&:hover:not(:active):not(:disabled):not([data-disabled]):not([aria-disabled=true])]:bg-primary/10 [&:active:not(:disabled):not([data-disabled]):not([aria-disabled=true])]:bg-primary/20";
|
|
7
|
+
readonly destructiveInteractive: "[&:hover:not(:active):not(:disabled):not([data-disabled]):not([aria-disabled=true])]:bg-destructive/10 [&:active:not(:disabled):not([data-disabled]):not([aria-disabled=true])]:bg-destructive/20";
|
|
8
|
+
readonly successInteractive: "[&:hover:not(:active):not(:disabled):not([data-disabled]):not([aria-disabled=true])]:bg-success/10 [&:active:not(:disabled):not([data-disabled]):not([aria-disabled=true])]:bg-success/20";
|
|
9
|
+
readonly warningInteractive: "[&:hover:not(:active):not(:disabled):not([data-disabled]):not([aria-disabled=true])]:bg-warning/10 [&:active:not(:disabled):not([data-disabled]):not([aria-disabled=true])]:bg-warning/20";
|
|
10
|
+
readonly infoInteractive: "[&:hover:not(:active):not(:disabled):not([data-disabled]):not([aria-disabled=true])]:bg-info/10 [&:active:not(:disabled):not([data-disabled]):not([aria-disabled=true])]:bg-info/20";
|
|
10
11
|
readonly isLoading: "cursor-wait";
|
|
11
|
-
readonly styleSolid: "";
|
|
12
|
-
readonly styleOutline: "";
|
|
13
|
-
readonly styleGhost: "";
|
|
14
12
|
readonly icon: "base-button-icon pointer-events-none shrink-0";
|
|
15
|
-
readonly spinner: "animate-spin
|
|
16
|
-
readonly toneNeutral: "data-[style=solid]:bg-foreground data-[style=solid]:text-background data-[style=solid]:[&:hover:not(:disabled):not([aria-disabled=true])]:brightness-95 data-[style=outline]:bg-transparent data-[style=outline]:border-border data-[style=outline]:text-foreground data-[style=outline]:[&:hover:not(:disabled):not([aria-disabled=true])]:bg-muted data-[style=ghost]:bg-transparent data-[style=ghost]:text-foreground data-[style=ghost]:[&:hover:not(:disabled):not([aria-disabled=true])]:bg-muted";
|
|
17
|
-
readonly tonePrimary: "data-[style=solid]:bg-primary data-[style=solid]:text-primary-foreground data-[style=solid]:[&:hover:not(:disabled):not([aria-disabled=true])]:brightness-95 data-[style=outline]:bg-transparent data-[style=outline]:border-primary data-[style=outline]:text-primary-accent data-[style=outline]:[&:hover:not(:disabled):not([aria-disabled=true])]:bg-primary/10 data-[style=ghost]:bg-transparent data-[style=ghost]:text-primary-accent data-[style=ghost]:[&:hover:not(:disabled):not([aria-disabled=true])]:bg-primary/10";
|
|
18
|
-
readonly toneSecondary: "data-[style=solid]:bg-secondary data-[style=solid]:text-secondary-foreground data-[style=solid]:[&:hover:not(:disabled):not([aria-disabled=true])]:brightness-95 data-[style=outline]:bg-transparent data-[style=outline]:border-border data-[style=outline]:text-foreground data-[style=outline]:[&:hover:not(:disabled):not([aria-disabled=true])]:bg-secondary data-[style=ghost]:bg-transparent data-[style=ghost]:text-foreground data-[style=ghost]:[&:hover:not(:disabled):not([aria-disabled=true])]:bg-secondary";
|
|
19
|
-
readonly toneDestructive: "data-[style=solid]:bg-destructive data-[style=solid]:text-destructive-foreground data-[style=solid]:[&:hover:not(:disabled):not([aria-disabled=true])]:brightness-95 data-[style=outline]:bg-transparent data-[style=outline]:border-destructive data-[style=outline]:text-destructive data-[style=outline]:[&:hover:not(:disabled):not([aria-disabled=true])]:bg-destructive/10 data-[style=ghost]:bg-transparent data-[style=ghost]:text-destructive data-[style=ghost]:[&:hover:not(:disabled):not([aria-disabled=true])]:bg-destructive/10";
|
|
20
|
-
readonly toneSuccess: "data-[style=solid]:bg-success data-[style=solid]:text-success-foreground data-[style=solid]:[&:hover:not(:disabled):not([aria-disabled=true])]:brightness-95 data-[style=outline]:bg-transparent data-[style=outline]:border-success data-[style=outline]:text-success data-[style=outline]:[&:hover:not(:disabled):not([aria-disabled=true])]:bg-success/10 data-[style=ghost]:bg-transparent data-[style=ghost]:text-success data-[style=ghost]:[&:hover:not(:disabled):not([aria-disabled=true])]:bg-success/10";
|
|
21
|
-
readonly toneWarning: "data-[style=solid]:bg-warning data-[style=solid]:text-warning-foreground data-[style=solid]:[&:hover:not(:disabled):not([aria-disabled=true])]:brightness-95 data-[style=outline]:bg-transparent data-[style=outline]:border-warning data-[style=outline]:text-warning-accent data-[style=outline]:[&:hover:not(:disabled):not([aria-disabled=true])]:bg-warning/10 data-[style=ghost]:bg-transparent data-[style=ghost]:text-warning-accent data-[style=ghost]:[&:hover:not(:disabled):not([aria-disabled=true])]:bg-warning/10";
|
|
22
|
-
readonly toneInfo: "data-[style=solid]:bg-info data-[style=solid]:text-info-foreground data-[style=solid]:[&:hover:not(:disabled):not([aria-disabled=true])]:brightness-95 data-[style=outline]:bg-transparent data-[style=outline]:border-info data-[style=outline]:text-info data-[style=outline]:[&:hover:not(:disabled):not([aria-disabled=true])]:bg-info/10 data-[style=ghost]:bg-transparent data-[style=ghost]:text-info data-[style=ghost]:[&:hover:not(:disabled):not([aria-disabled=true])]:bg-info/10";
|
|
13
|
+
readonly spinner: "animate-spin";
|
|
23
14
|
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type ForwardedRef, type RefCallback } from 'react';
|
|
2
|
+
/** Native disabling can drop focused busy actions to body; restore only an unclaimed focus. */
|
|
3
|
+
export declare function usePendingButtonFocus(pending: boolean, forwardedRef: ForwardedRef<HTMLElement>): RefCallback<HTMLElement>;
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
/** Explicit region insets; omitted padding preserves the compound's inline-only defaults. */
|
|
2
|
+
export declare const cardRegionPaddingClasses: {
|
|
3
|
+
readonly none: "p-0";
|
|
4
|
+
readonly sm: "p-surface-xs";
|
|
5
|
+
readonly md: "p-surface";
|
|
6
|
+
readonly lg: "p-surface-lg";
|
|
7
|
+
};
|
|
1
8
|
/** Private Tailwind recipes; public props and DOM hooks remain owned by the component. */
|
|
2
9
|
export declare const cardRecipes: {
|
|
3
|
-
readonly root: "flex flex-col w-full rounded-radius box-border overflow-hidden py-surface gap-space-xl transition-[background-color,border-color,box-shadow] duration-150";
|
|
4
|
-
readonly shell: "@container/card flex flex-col w-full rounded-radius box-border overflow-hidden py-surface gap-space-xl transition-[background-color,border-color,box-shadow] duration-150";
|
|
10
|
+
readonly root: "flex flex-col w-full font-sans rounded-radius box-border overflow-hidden py-surface gap-space-xl transition-[background-color,border-color,box-shadow] duration-150";
|
|
11
|
+
readonly shell: "@container/card flex flex-col w-full font-sans rounded-radius box-border overflow-hidden py-surface gap-space-xl transition-[background-color,border-color,box-shadow] duration-150";
|
|
5
12
|
readonly surfaceCard: "bg-card border border-border shadow-sm text-card-foreground";
|
|
6
13
|
readonly surfaceDefault: "bg-card border border-border shadow-sm text-card-foreground";
|
|
7
14
|
readonly surfaceFlat: "bg-transparent border-0 shadow-none text-foreground";
|
|
@@ -9,9 +16,10 @@ export declare const cardRecipes: {
|
|
|
9
16
|
readonly surfaceRaised: "bg-card border border-border shadow-md text-card-foreground";
|
|
10
17
|
readonly surfaceSunken: "bg-muted border border-border text-foreground";
|
|
11
18
|
readonly header: "flex flex-col gap-normal px-surface box-border";
|
|
12
|
-
readonly headerRow: "flex-
|
|
13
|
-
readonly headerRowSingle: "
|
|
14
|
-
readonly headerLeading: "min-w-0 w-full
|
|
19
|
+
readonly headerRow: "flex-row flex-wrap items-start justify-between gap-space-lg pb-0";
|
|
20
|
+
readonly headerRowSingle: "items-center";
|
|
21
|
+
readonly headerLeading: "min-w-0 max-w-full flex-1 basis-64";
|
|
22
|
+
readonly headerLeadingSingle: "basis-36";
|
|
15
23
|
readonly headerTrailing: "flex max-w-full flex-wrap shrink-0 items-center gap-space-md";
|
|
16
24
|
readonly headerDivider: "border-b border-border [&.border-b]:!pb-surface";
|
|
17
25
|
readonly title: "min-w-0 leading-tight text-card-foreground";
|
|
@@ -8,14 +8,19 @@ import type { TextGap } from '../../structure';
|
|
|
8
8
|
* applied here so the public DOM contract lives in one place.
|
|
9
9
|
*/
|
|
10
10
|
import { type ComponentPropsWithRef, type ComponentPropsWithoutRef } from 'react';
|
|
11
|
-
import type { CardTitleSize } from '../smart-card.types';
|
|
11
|
+
import type { CardTitleSize, SmartCardProps } from '../smart-card.types';
|
|
12
|
+
type CardRegionProps = ComponentPropsWithRef<'div'> & {
|
|
13
|
+
/** Full surface inset. Omit to retain the established inline-only inset. */
|
|
14
|
+
padding?: SmartCardProps['padding'];
|
|
15
|
+
};
|
|
12
16
|
export declare function CardShell({ className, ...props }: ComponentPropsWithRef<'div'>): import("react").JSX.Element;
|
|
13
|
-
export declare function CardHeader({ className, textGap, ...props }:
|
|
17
|
+
export declare function CardHeader({ className, textGap, padding, ...props }: CardRegionProps & {
|
|
14
18
|
textGap?: TextGap;
|
|
15
19
|
}): import("react").JSX.Element;
|
|
16
20
|
export declare function CardTitle({ className, children, size: sizeProp, ...props }: ComponentPropsWithoutRef<'div'> & {
|
|
17
21
|
size?: CardTitleSize;
|
|
18
22
|
}): import("react").JSX.Element | null;
|
|
19
23
|
export declare function CardDescription({ className, children, ...props }: ComponentPropsWithoutRef<'div'>): import("react").JSX.Element | null;
|
|
20
|
-
export declare function CardContent({ className, ...props }:
|
|
21
|
-
export declare function CardFooter({ className, ...props }:
|
|
24
|
+
export declare function CardContent({ className, padding, ...props }: CardRegionProps): import("react").JSX.Element;
|
|
25
|
+
export declare function CardFooter({ className, padding, ...props }: CardRegionProps): import("react").JSX.Element;
|
|
26
|
+
export {};
|
|
@@ -71,6 +71,8 @@ export interface SmartCardProps extends Omit<ComponentPropsWithoutRef<'div'>, 'c
|
|
|
71
71
|
padding?: 'none' | 'sm' | 'md' | 'lg';
|
|
72
72
|
/** `frame` places header/actions above an inset body surface. */
|
|
73
73
|
headerPlacement?: 'inside' | 'frame';
|
|
74
|
+
/** Semantic gap between header, body and footer regions. Defaults to `xl`; insets remain owned by padding. */
|
|
75
|
+
gap?: StructureGap;
|
|
74
76
|
/** Semantic gap between direct body children. */
|
|
75
77
|
contentGap?: StructureGap;
|
|
76
78
|
/** Card title typography scale. Defaults to `UIProvider.density.defaultScale`. */
|
|
@@ -107,7 +109,7 @@ export interface SmartCardProps extends Omit<ComponentPropsWithoutRef<'div'>, 'c
|
|
|
107
109
|
* With no body/alert, header and footer share one footer-owned divider.
|
|
108
110
|
*/
|
|
109
111
|
headerDivider?: boolean;
|
|
110
|
-
/**
|
|
112
|
+
/** Footer rule inherits UIProvider.card.defaultFooterDivider; false suppresses it. Adjacent header/footer regions share one rule. */
|
|
111
113
|
footerDivider?: boolean;
|
|
112
114
|
/**
|
|
113
115
|
* Make the card body collapsible. Pass `true` for default behavior
|
|
@@ -1,18 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* Mirrors the `Input` component's chrome:
|
|
7
|
-
* - `border-input` border, `rounded-radius-md`, `bg-transparent`
|
|
8
|
-
* - `h-control` + `px-control` + `py-space-xs`
|
|
9
|
-
* - `text-sm` body text, normal weight, `text-foreground`
|
|
10
|
-
* - `focus-visible:border-ring ring-ring/50 ring-[3px]`
|
|
11
|
-
* - `aria-invalid:` destructive ring + border
|
|
12
|
-
* - flat (no shadow) — library is intentionally flat
|
|
13
|
-
*
|
|
14
|
-
* `!` prefix wins against the global `<Button>`'s pill-shaped default
|
|
15
|
-
* + `data-[size=*]` attribute selectors. Caret-icon sits in
|
|
16
|
-
* library-default left padding equal to `<Input startIcon>` rules.
|
|
17
|
-
*/
|
|
18
|
-
export declare const PICKER_TRIGGER_CHROME: string;
|
|
1
|
+
import { type FormControlSize } from '../../../lib/ui-provider';
|
|
2
|
+
/** Picker triggers resolve the same explicit/provider/default scale as fields. */
|
|
3
|
+
export declare function usePickerTriggerSize(sizeProp: FormControlSize | undefined): FormControlSize;
|
|
4
|
+
/** Button composition contributes behavior; the shared field owner supplies chrome. */
|
|
5
|
+
export declare function pickerTriggerClasses(size: FormControlSize, iconOnly?: boolean): string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { LucideIcon } from 'lucide-react';
|
|
2
2
|
import type { DateRange, PropsSingle, PropsRange, PropsMulti, Locale } from 'react-day-picker';
|
|
3
|
+
import type { FormControlSize } from '../../../lib/ui-provider';
|
|
3
4
|
import type { StringsProp } from '../../../lib/strings';
|
|
4
5
|
import type { ActionPresentation } from '../../../lib/action-presentation';
|
|
5
6
|
import type { ButtonStyle, ButtonTone } from '../buttons';
|
|
@@ -64,6 +65,8 @@ export interface DatePickerStrings {
|
|
|
64
65
|
year: string;
|
|
65
66
|
}
|
|
66
67
|
export interface DatePickerBaseProps {
|
|
68
|
+
/** Trigger field size. Explicit values override the provider density scale; fallback is md. */
|
|
69
|
+
size?: FormControlSize;
|
|
67
70
|
/** Caption above the trigger, associated through `htmlFor`. Omit when an external FormField owns the chrome. */
|
|
68
71
|
label?: string;
|
|
69
72
|
/** Short guidance shown beside the label. Suppressed while `error` is set. */
|
|
@@ -31,6 +31,7 @@ export interface FieldChromeProps {
|
|
|
31
31
|
}
|
|
32
32
|
export interface FormFieldProps extends FieldChromeProps, Omit<ComponentPropsWithoutRef<'div'>, 'children'> {
|
|
33
33
|
children: ReactNode;
|
|
34
|
+
/** Native ID of the labelled control. With compound children, assign it to the nested control; passive wrappers are left untouched. Direct controls receive an automatic ID when omitted. */
|
|
34
35
|
htmlFor?: string;
|
|
35
36
|
/** ID for the resolved hint, helper, or error; controls can reference it explicitly. */
|
|
36
37
|
supportingTextId?: string;
|
|
@@ -27,12 +27,12 @@ export declare const formControlIconClasses: {
|
|
|
27
27
|
export declare const formControlIconOffsetClasses: {
|
|
28
28
|
sm: string;
|
|
29
29
|
md: string;
|
|
30
|
-
lg: "ps-[calc((var(--control-x)+
|
|
30
|
+
lg: "ps-[calc((var(--control-x)+0.5rem)*var(--space-scale)+var(--icon)*1.25)]";
|
|
31
31
|
};
|
|
32
32
|
export declare const formControlEndIconOffsetClasses: {
|
|
33
33
|
sm: string;
|
|
34
34
|
md: string;
|
|
35
|
-
lg: "pe-[calc((var(--control-x)+
|
|
35
|
+
lg: "pe-[calc((var(--control-x)+0.5rem)*var(--space-scale)+var(--icon)*1.25)]";
|
|
36
36
|
};
|
|
37
37
|
export declare const formControlAddonOffsetClasses: {
|
|
38
38
|
sm: string;
|
|
@@ -63,7 +63,7 @@ export declare const formControlMinHeightClasses: {
|
|
|
63
63
|
* Canonical "input-shaped trigger" chrome — used by any control that
|
|
64
64
|
* renders as a button-style trigger but visually has to read as a form
|
|
65
65
|
* field (DatePicker, TimePicker, the inner Select inside composite
|
|
66
|
-
* fields, etc.). Mirrors `Input`'s `border-input rounded-
|
|
66
|
+
* fields, etc.). Mirrors `Input`'s `border-input rounded-inner
|
|
67
67
|
* bg-transparent focus-visible:ring` chrome (no shadow — the library
|
|
68
68
|
* is intentionally flat) plus the size-driven height + horizontal
|
|
69
69
|
* padding.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type StringsProp } from '../../../lib/strings';
|
|
3
|
+
import { type InputProps, type TextareaProps } from '../text-inputs';
|
|
4
|
+
export interface InlineEditStrings {
|
|
5
|
+
/** Accessible name of the edit action when editLabel is absent. */
|
|
6
|
+
edit: string;
|
|
7
|
+
/** Accessible name of the save action. */
|
|
8
|
+
save: string;
|
|
9
|
+
/** Accessible name of the cancel action, including while saving. */
|
|
10
|
+
cancel: string;
|
|
11
|
+
/** Live announcement and save action name during persistence. */
|
|
12
|
+
saving: string;
|
|
13
|
+
/** Validation copy for a required empty value. */
|
|
14
|
+
required: string;
|
|
15
|
+
/** Fallback copy for a rejected save without an Error message. */
|
|
16
|
+
saveError: string;
|
|
17
|
+
/** Display copy for an empty value when placeholder is absent. */
|
|
18
|
+
empty: string;
|
|
19
|
+
}
|
|
20
|
+
export declare const defaultInlineEditStrings: InlineEditStrings;
|
|
21
|
+
export interface InlineEditSaveContext {
|
|
22
|
+
/** Aborted on cancel, unmount, external value replacement, or external dismissal. */
|
|
23
|
+
signal: AbortSignal;
|
|
24
|
+
}
|
|
25
|
+
type SharedControlProps = Pick<InputProps, 'size' | 'invalid' | 'loading' | 'clearable' | 'onClear' | 'showCharacterCount'>;
|
|
26
|
+
type OwnedEditorProps = keyof SharedControlProps | 'value' | 'defaultValue' | 'onChange' | 'ref' | 'id' | 'name' | 'form' | 'required' | 'disabled' | 'readOnly' | 'placeholder' | 'autoComplete' | 'maxLength' | 'rows' | 'returnValueWithAddons';
|
|
27
|
+
export interface InlineEditProps extends SharedControlProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'children' | 'defaultValue' | 'onChange'> {
|
|
28
|
+
/** Native Input attributes, adornments and strings. Draft/state ownership stays with InlineEdit. */
|
|
29
|
+
inputProps?: Omit<InputProps, OwnedEditorProps>;
|
|
30
|
+
/** Native Textarea attributes, resizing options and strings. Draft/state ownership stays with InlineEdit. */
|
|
31
|
+
textareaProps?: Omit<TextareaProps, OwnedEditorProps>;
|
|
32
|
+
/** Committed value. Draft edits remain local until save succeeds. */
|
|
33
|
+
value?: string;
|
|
34
|
+
/** Initial committed value for uncontrolled usage. */
|
|
35
|
+
defaultValue?: string;
|
|
36
|
+
/** Called with the new committed value after a successful changed save. */
|
|
37
|
+
onValueChange?: (value: string) => void;
|
|
38
|
+
/** Controlled editor visibility. */
|
|
39
|
+
editing?: boolean;
|
|
40
|
+
/** Initial visibility for uncontrolled usage. */
|
|
41
|
+
defaultEditing?: boolean;
|
|
42
|
+
/** Requests a visibility change; controlled parents must update editing. */
|
|
43
|
+
onEditingChange?: (editing: boolean) => void;
|
|
44
|
+
/** Uses Textarea. Plain Enter inserts a newline; Ctrl/Cmd+Enter saves. */
|
|
45
|
+
multiline?: boolean;
|
|
46
|
+
/** Field caption above both presentation and editing states. */
|
|
47
|
+
label?: React.ReactNode;
|
|
48
|
+
/** Supporting copy, replaced by a validation or save error when present. */
|
|
49
|
+
description?: React.ReactNode;
|
|
50
|
+
/** Empty display copy and editor placeholder. */
|
|
51
|
+
placeholder?: string;
|
|
52
|
+
/** Accessible edit action name, useful when the display is a title. */
|
|
53
|
+
editLabel?: string;
|
|
54
|
+
/** Custom passive display content. Do not nest interactive elements. */
|
|
55
|
+
renderValue?: (value: string) => React.ReactNode;
|
|
56
|
+
/** Prevents editing and disables the edit action. */
|
|
57
|
+
disabled?: boolean;
|
|
58
|
+
/** Renders passive content with no edit action. */
|
|
59
|
+
readOnly?: boolean;
|
|
60
|
+
/** Save-time validation for an empty draft; marks the editor aria-required without constraining the parent form. */
|
|
61
|
+
required?: boolean;
|
|
62
|
+
/** Return an error message to keep the draft open without calling onSave. */
|
|
63
|
+
validate?: (value: string) => string | undefined | null;
|
|
64
|
+
/** Persist the draft; rejection keeps it open for correction or retry. */
|
|
65
|
+
onSave?: (value: string, context: InlineEditSaveContext) => void | Promise<void>;
|
|
66
|
+
/** Native form field name. Only the committed value is submitted. */
|
|
67
|
+
name?: string;
|
|
68
|
+
/** Associates the committed hidden field with a native form. */
|
|
69
|
+
form?: string;
|
|
70
|
+
/** Native editor autocomplete hint. */
|
|
71
|
+
autoComplete?: string;
|
|
72
|
+
/** Maximum editor character count. */
|
|
73
|
+
maxLength?: number;
|
|
74
|
+
/** Native Textarea row count. */
|
|
75
|
+
rows?: number;
|
|
76
|
+
/** Localized component copy. */
|
|
77
|
+
strings?: StringsProp<InlineEditStrings>;
|
|
78
|
+
}
|
|
79
|
+
/** Inline text editing with an isolated draft and explicit, cancellable saves. */
|
|
80
|
+
export declare const InlineEdit: React.ForwardRefExoticComponent<InlineEditProps & React.RefAttributes<HTMLDivElement>>;
|
|
81
|
+
export {};
|