@lobehub/ui 5.64.1 → 5.64.3
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/README.md +3 -3
- package/es/EmojiPicker/EmojiPicker.mjs +2 -2
- package/es/Form/Form.mjs +6 -2
- package/es/Form/Form.mjs.map +1 -1
- package/es/Form/style.mjs +3 -2
- package/es/Form/style.mjs.map +1 -1
- package/es/Form/type.d.mts +10 -0
- package/es/base-ui/DatePicker/DatePicker.d.mts +5 -3
- package/es/base-ui/DatePicker/DatePicker.mjs +7 -5
- package/es/base-ui/DatePicker/DatePicker.mjs.map +1 -1
- package/es/base-ui/DatePicker/DateRangePicker.d.mts +1 -1
- package/es/base-ui/DatePicker/DayjsDatePicker.d.mts +12 -0
- package/es/base-ui/DatePicker/DayjsDatePicker.mjs +19 -0
- package/es/base-ui/DatePicker/DayjsDatePicker.mjs.map +1 -0
- package/es/base-ui/DatePicker/DayjsDateRangePicker.d.mts +7 -0
- package/es/base-ui/DatePicker/DayjsDateRangePicker.mjs +8 -0
- package/es/base-ui/DatePicker/DayjsDateRangePicker.mjs.map +1 -0
- package/es/base-ui/DatePicker/RangePicker.mjs +7 -1
- package/es/base-ui/DatePicker/RangePicker.mjs.map +1 -1
- package/es/base-ui/DatePicker/SinglePicker.mjs +3 -1
- package/es/base-ui/DatePicker/SinglePicker.mjs.map +1 -1
- package/es/base-ui/DatePicker/dateGenerateConfig.mjs +52 -0
- package/es/base-ui/DatePicker/dateGenerateConfig.mjs.map +1 -0
- package/es/base-ui/DatePicker/index.d.mts +4 -2
- package/es/base-ui/DatePicker/legacyDate.mjs +58 -0
- package/es/base-ui/DatePicker/legacyDate.mjs.map +1 -0
- package/es/base-ui/DatePicker/type.d.mts +65 -39
- package/es/base-ui/DatePicker/usePresetActive.mjs +1 -0
- package/es/base-ui/DatePicker/usePresetActive.mjs.map +1 -1
- package/es/base-ui/Form/Form.mjs +6 -2
- package/es/base-ui/Form/Form.mjs.map +1 -1
- package/es/base-ui/Form/style.mjs +3 -2
- package/es/base-ui/Form/style.mjs.map +1 -1
- package/es/base-ui/Form/type.d.mts +7 -0
- package/es/base-ui/Input/style.d.mts +1 -1
- package/es/base-ui/ProTable/FieldControl.mjs +32 -15
- package/es/base-ui/ProTable/FieldControl.mjs.map +1 -1
- package/es/base-ui/ProTable/style.mjs +14 -1
- package/es/base-ui/ProTable/style.mjs.map +1 -1
- package/es/base-ui/ProTable/type.d.mts +5 -2
- package/es/base-ui/ProTable/useFetchData.mjs +1 -1
- package/es/base-ui/ProTable/useFetchData.mjs.map +1 -1
- package/es/base-ui/Switch/Switch.mjs +7 -1
- package/es/base-ui/Switch/Switch.mjs.map +1 -1
- package/es/base-ui/Switch/atoms.mjs +17 -2
- package/es/base-ui/Switch/atoms.mjs.map +1 -1
- package/es/base-ui/Switch/style.d.mts +4 -0
- package/es/base-ui/Switch/style.mjs +47 -2
- package/es/base-ui/Switch/style.mjs.map +1 -1
- package/es/base-ui/Table/FixedFrost.mjs +15 -2
- package/es/base-ui/Table/FixedFrost.mjs.map +1 -1
- package/es/base-ui/Table/Table.mjs +13 -3
- package/es/base-ui/Table/Table.mjs.map +1 -1
- package/es/base-ui/index.d.mts +4 -2
- package/es/base-ui/index.mjs +3 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.mjs","names":[],"sources":["../../../src/base-ui/ProTable/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const PRO_PREFIX_CLS = 'lobe-pro-table';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n alert: css`\n display: flex;\n gap: 12px;\n align-items: center;\n justify-content: space-between;\n\n min-height: 40px;\n margin-block-end: 12px;\n padding-block: 6px;\n padding-inline: 12px;\n border-radius: ${cssVar.borderRadius};\n\n font-size: ${cssVar.fontSize};\n color: ${cssVar.colorText};\n\n background: color-mix(in srgb, ${cssVar.colorPrimary} 8%, transparent);\n `,\n alertInfo: css`\n display: flex;\n flex: 1;\n flex-wrap: wrap;\n gap: 12px;\n align-items: center;\n\n min-width: 0;\n `,\n alertOption: css`\n display: flex;\n flex: none;\n gap: 8px;\n align-items: center;\n `,\n part: css`\n min-width: 0;\n `,\n partBordered: css`\n padding: 16px;\n border: 1px solid ${cssVar.colorBorderSecondary};\n border-radius: ${cssVar.borderRadiusLG};\n `,\n code: css`\n padding-block: 1px;\n padding-inline: 6px;\n border-radius: ${cssVar.borderRadiusSM};\n\n font-family: ${cssVar.fontFamilyCode};\n font-size: 0.9em;\n\n background: ${cssVar.colorFillTertiary};\n `,\n copyable: css`\n display: inline-flex;\n gap: 4px;\n align-items: center;\n max-width: 100%;\n `,\n copyableText: css`\n overflow: hidden;\n min-width: 0;\n text-overflow: ellipsis;\n `,\n density: css`\n display: flex;\n flex-direction: column;\n min-width: 140px;\n padding: 4px;\n `,\n densityItem: css`\n cursor: pointer;\n\n display: flex;\n gap: 8px;\n align-items: center;\n justify-content: space-between;\n\n height: 32px;\n padding-inline: 8px;\n border: none;\n border-radius: ${cssVar.borderRadiusSM};\n\n font: inherit;\n color: ${cssVar.colorText};\n text-align: start;\n\n background: transparent;\n\n &:hover,\n &:focus-visible {\n background: ${cssVar.colorFillTertiary};\n outline: none;\n }\n\n &[aria-checked='true'] {\n font-weight: 500;\n }\n `,\n enumList: css`\n display: inline-flex;\n flex-wrap: wrap;\n gap: 8px;\n `,\n indexBorder: css`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n min-width: 18px;\n height: 18px;\n padding-inline: 4px;\n border-radius: 9px;\n\n font-size: 12px;\n font-variant-numeric: tabular-nums;\n color: ${cssVar.colorText};\n\n background: ${cssVar.colorFillSecondary};\n\n &[data-top] {\n color: ${cssVar.colorTextLightSolid};\n background: ${cssVar.colorPrimary};\n }\n `,\n lightFilter: css`\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n `,\n lightFilterItem: css`\n display: inline-flex;\n flex: none;\n align-items: center;\n width: 160px;\n\n & > * {\n width: 100%;\n }\n `,\n lightFilterLabel: css`\n font-size: ${cssVar.fontSizeSM};\n color: ${cssVar.colorTextSecondary};\n white-space: nowrap;\n `,\n optionCell: css`\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n align-items: center;\n justify-content: flex-end;\n `,\n root: css`\n --lobe-pro-table-status-default: ${cssVar.colorTextQuaternary};\n --lobe-pro-table-status-error: ${cssVar.colorError};\n --lobe-pro-table-status-processing: ${cssVar.colorPrimary};\n --lobe-pro-table-status-success: ${cssVar.colorSuccess};\n --lobe-pro-table-status-warning: ${cssVar.colorWarning};\n\n display: flex;\n flex-direction: column;\n gap: 16px;\n min-width: 0;\n\n /* Query form → toolbar / table: 24px (16px gap + 8px), parts below keep 16px. */\n & > :has(> [data-pro-table-search]) {\n margin-block-end: 8px;\n }\n\n &[data-fullscreen] {\n overflow: auto;\n padding: 16px;\n background: ${cssVar.colorBgLayout};\n }\n `,\n search: css`\n display: grid;\n gap: 16px 24px;\n align-items: center;\n `,\n searchActions: css`\n display: flex;\n grid-column-end: -1;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n justify-content: flex-end;\n\n /* Vertical: buttons sit on the control line of the last row (Pro adds a blank label). */\n &[data-layout='vertical'] {\n align-self: end;\n }\n `,\n /* Ellipsis lives on the element that holds the text (Form wraps labels in flex boxes). */\n searchLabelText: css`\n overflow: hidden;\n display: block;\n\n min-width: 0;\n max-width: 100%;\n\n text-overflow: ellipsis;\n white-space: nowrap;\n `,\n searchField: css`\n min-width: 0;\n\n /* The base-ui Form.Field row: no list padding, fixed-width label column, full-width control. */\n & > div {\n gap: 8px;\n padding-block: 0;\n }\n\n & > div > label {\n overflow: hidden;\n flex: none;\n\n width: var(--lobe-pro-table-label-width, auto);\n\n color: ${cssVar.colorTextSecondary};\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n &[data-layout='horizontal'] > div > label {\n text-align: end;\n }\n\n /* A long label never leaves the form: a block label clips and ellipsizes at the END of\n the text (text-align only moves short labels; it never shifts overflow to the start). */\n && > div > label {\n min-width: 0;\n max-width: 100%;\n }\n\n && > div > label * {\n min-width: 0;\n max-width: 100%;\n }\n\n /* Vertical (Pro QueryFilter vertical): label on its own line, full-width control. */\n &[data-layout='vertical'] > div > label {\n width: 100%;\n text-align: start;\n }\n\n & > div > div {\n flex: 1;\n align-items: stretch;\n min-width: 0;\n }\n `,\n searchFieldControl: css`\n flex: 1;\n min-width: 0;\n `,\n searchLabel: css`\n overflow: hidden;\n flex: none;\n\n color: ${cssVar.colorTextSecondary};\n text-align: end;\n text-overflow: ellipsis;\n white-space: nowrap;\n\n &[data-layout='vertical'] {\n text-align: start;\n }\n `,\n setting: css`\n display: flex;\n flex-direction: column;\n\n width: 260px;\n max-height: 420px;\n padding-block: 4px;\n `,\n settingGroupTitle: css`\n padding-block: 6px 2px;\n padding-inline: 12px;\n font-size: ${cssVar.fontSizeSM};\n color: ${cssVar.colorTextDescription};\n `,\n settingHeader: css`\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding-block: 4px 8px;\n padding-inline: 12px;\n border-block-end: 1px solid ${cssVar.colorSplit};\n `,\n settingItem: css`\n display: flex;\n gap: 4px;\n align-items: center;\n\n min-height: 32px;\n padding-inline: 12px 8px;\n\n &:hover {\n background: ${cssVar.colorFillTertiary};\n }\n\n &:hover [data-setting-actions] {\n opacity: 1;\n }\n `,\n settingItemActions: css`\n display: flex;\n flex: none;\n gap: 2px;\n opacity: 0;\n\n &:focus-within {\n opacity: 1;\n }\n `,\n settingItemTitle: css`\n overflow: hidden;\n flex: 1;\n\n min-width: 0;\n\n text-overflow: ellipsis;\n white-space: nowrap;\n `,\n settingList: css`\n overflow: auto;\n flex: 1;\n padding-block: 4px;\n `,\n status: css`\n display: inline-flex;\n gap: 8px;\n align-items: center;\n `,\n statusDot: css`\n flex: none;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n `,\n statusProcessing: css`\n @keyframes lobe-pro-table-status-pulse {\n 0% {\n box-shadow: 0 0 0 0 color-mix(in srgb, currentcolor 40%, transparent);\n }\n\n 100% {\n box-shadow: 0 0 0 4px transparent;\n }\n }\n\n color: ${cssVar.colorPrimary};\n animation: lobe-pro-table-status-pulse 1.2s ease-out infinite;\n `,\n title: css`\n display: flex;\n flex: none;\n gap: 4px;\n align-items: center;\n\n min-width: 0;\n\n font-size: ${cssVar.fontSizeLG};\n font-weight: 600;\n color: ${cssVar.colorText};\n `,\n titleSub: css`\n font-size: ${cssVar.fontSize};\n font-weight: normal;\n color: ${cssVar.colorTextDescription};\n `,\n titleTooltip: css`\n display: inline-flex;\n gap: 4px;\n align-items: center;\n `,\n toolbar: css`\n display: flex;\n flex-wrap: nowrap;\n gap: 12px;\n align-items: center;\n justify-content: space-between;\n\n margin-block-end: 16px;\n `,\n toolbarActions: css`\n display: flex;\n flex: 1;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n justify-content: flex-end;\n\n min-width: 0;\n margin-inline-start: auto;\n `,\n toolbarOptions: css`\n display: flex;\n flex: none;\n gap: 2px;\n align-items: center;\n `,\n}));\n"],"mappings":";;AAEA,MAAa,iBAAiB;AAE9B,MAAa,SAAS,oBAAoB,EAAE,KAAK,cAAc;CAC7D,OAAO,GAAG;;;;;;;;;;qBAUS,OAAO,aAAa;;iBAExB,OAAO,SAAS;aACpB,OAAO,UAAU;;qCAEO,OAAO,aAAa;;CAEvD,WAAW,GAAG;;;;;;;;;CASd,aAAa,GAAG;;;;;;CAMhB,MAAM,GAAG;;;CAGT,cAAc,GAAG;;wBAEK,OAAO,qBAAqB;qBAC/B,OAAO,eAAe;;CAEzC,MAAM,GAAG;;;qBAGU,OAAO,eAAe;;mBAExB,OAAO,eAAe;;;kBAGvB,OAAO,kBAAkB;;CAEzC,UAAU,GAAG;;;;;;CAMb,cAAc,GAAG;;;;;CAKjB,SAAS,GAAG;;;;;;CAMZ,aAAa,GAAG;;;;;;;;;;;qBAWG,OAAO,eAAe;;;aAG9B,OAAO,UAAU;;;;;;;oBAOV,OAAO,kBAAkB;;;;;;;;CAQ3C,UAAU,GAAG;;;;;CAKb,aAAa,GAAG;;;;;;;;;;;;aAYL,OAAO,UAAU;;kBAEZ,OAAO,mBAAmB;;;eAG7B,OAAO,oBAAoB;oBACtB,OAAO,aAAa;;;CAGtC,aAAa,GAAG;;;;;;CAMhB,iBAAiB,GAAG;;;;;;;;;;CAUpB,kBAAkB,GAAG;iBACN,OAAO,WAAW;aACtB,OAAO,mBAAmB;;;CAGrC,YAAY,GAAG;;;;;;;CAOf,MAAM,GAAG;uCAC4B,OAAO,oBAAoB;qCAC7B,OAAO,WAAW;0CACb,OAAO,aAAa;uCACvB,OAAO,aAAa;uCACpB,OAAO,aAAa;;;;;;;;;;;;;;;oBAevC,OAAO,cAAc;;;CAGvC,QAAQ,GAAG;;;;;CAKX,eAAe,GAAG;;;;;;;;;;;;;CAclB,iBAAiB,GAAG;;;;;;;;;;CAUpB,aAAa,GAAG;;;;;;;;;;;;;;;eAeH,OAAO,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCvC,oBAAoB,GAAG;;;;CAIvB,aAAa,GAAG;;;;aAIL,OAAO,mBAAmB;;;;;;;;;CASrC,SAAS,GAAG;;;;;;;;CAQZ,mBAAmB,GAAG;;;iBAGP,OAAO,WAAW;aACtB,OAAO,qBAAqB;;CAEvC,eAAe,GAAG;;;;;;;kCAOc,OAAO,WAAW;;CAElD,aAAa,GAAG;;;;;;;;;oBASE,OAAO,kBAAkB;;;;;;;CAO3C,oBAAoB,GAAG;;;;;;;;;;CAUvB,kBAAkB,GAAG;;;;;;;;;CASrB,aAAa,GAAG;;;;;CAKhB,QAAQ,GAAG;;;;;CAKX,WAAW,GAAG;;;;;;CAMd,kBAAkB,GAAG;;;;;;;;;;;aAWV,OAAO,aAAa;;;CAG/B,OAAO,GAAG;;;;;;;;iBAQK,OAAO,WAAW;;aAEtB,OAAO,UAAU;;CAE5B,UAAU,GAAG;iBACE,OAAO,SAAS;;aAEpB,OAAO,qBAAqB;;CAEvC,cAAc,GAAG;;;;;CAKjB,SAAS,GAAG;;;;;;;;;CASZ,gBAAgB,GAAG;;;;;;;;;;;CAWnB,gBAAgB,GAAG;;;;;;AAMrB,EAAE"}
|
|
1
|
+
{"version":3,"file":"style.mjs","names":[],"sources":["../../../src/base-ui/ProTable/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const PRO_PREFIX_CLS = 'lobe-pro-table';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n alert: css`\n display: flex;\n gap: 12px;\n align-items: center;\n justify-content: space-between;\n\n min-height: 40px;\n margin-block-end: 12px;\n padding-block: 6px;\n padding-inline: 12px;\n border-radius: ${cssVar.borderRadius};\n\n font-size: ${cssVar.fontSize};\n color: ${cssVar.colorText};\n\n background: color-mix(in srgb, ${cssVar.colorPrimary} 8%, transparent);\n `,\n alertInfo: css`\n display: flex;\n flex: 1;\n flex-wrap: wrap;\n gap: 12px;\n align-items: center;\n\n min-width: 0;\n `,\n alertOption: css`\n display: flex;\n flex: none;\n gap: 8px;\n align-items: center;\n `,\n part: css`\n min-width: 0;\n `,\n partBordered: css`\n padding: 16px;\n border: 1px solid ${cssVar.colorBorderSecondary};\n border-radius: ${cssVar.borderRadiusLG};\n `,\n code: css`\n padding-block: 1px;\n padding-inline: 6px;\n border-radius: ${cssVar.borderRadiusSM};\n\n font-family: ${cssVar.fontFamilyCode};\n font-size: 0.9em;\n\n background: ${cssVar.colorFillTertiary};\n `,\n copyable: css`\n display: inline-flex;\n gap: 4px;\n align-items: center;\n max-width: 100%;\n `,\n copyableText: css`\n overflow: hidden;\n min-width: 0;\n text-overflow: ellipsis;\n `,\n density: css`\n display: flex;\n flex-direction: column;\n min-width: 140px;\n padding: 4px;\n `,\n densityItem: css`\n cursor: pointer;\n\n display: flex;\n gap: 8px;\n align-items: center;\n justify-content: space-between;\n\n height: 32px;\n padding-inline: 8px;\n border: none;\n border-radius: ${cssVar.borderRadiusSM};\n\n font: inherit;\n color: ${cssVar.colorText};\n text-align: start;\n\n background: transparent;\n\n &:hover,\n &:focus-visible {\n background: ${cssVar.colorFillTertiary};\n outline: none;\n }\n\n &[aria-checked='true'] {\n font-weight: 500;\n }\n `,\n enumList: css`\n display: inline-flex;\n flex-wrap: wrap;\n gap: 8px;\n `,\n indexBorder: css`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n\n min-width: 18px;\n height: 18px;\n padding-inline: 4px;\n border-radius: 9px;\n\n font-size: 12px;\n font-variant-numeric: tabular-nums;\n color: ${cssVar.colorText};\n\n background: ${cssVar.colorFillSecondary};\n\n &[data-top] {\n color: ${cssVar.colorTextLightSolid};\n background: ${cssVar.colorPrimary};\n }\n `,\n lightFilter: css`\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n `,\n lightFilterItem: css`\n display: inline-flex;\n flex: none;\n align-items: center;\n\n width: auto;\n min-width: 160px;\n max-width: 320px;\n\n & > * {\n width: 100%;\n }\n `,\n lightFilterLabel: css`\n flex: none;\n font-size: ${cssVar.fontSizeSM};\n color: ${cssVar.colorTextSecondary};\n white-space: nowrap;\n\n &::after {\n content: ':';\n }\n `,\n lightFilterSwitch: css`\n display: inline-flex;\n gap: 8px;\n align-items: center;\n `,\n optionCell: css`\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n align-items: center;\n justify-content: flex-end;\n `,\n root: css`\n --lobe-pro-table-status-default: ${cssVar.colorTextQuaternary};\n --lobe-pro-table-status-error: ${cssVar.colorError};\n --lobe-pro-table-status-processing: ${cssVar.colorPrimary};\n --lobe-pro-table-status-success: ${cssVar.colorSuccess};\n --lobe-pro-table-status-warning: ${cssVar.colorWarning};\n\n display: flex;\n flex-direction: column;\n gap: 16px;\n min-width: 0;\n\n /* Query form → toolbar / table: 24px (16px gap + 8px), parts below keep 16px. */\n & > :has(> [data-pro-table-search]) {\n margin-block-end: 8px;\n }\n\n &[data-fullscreen] {\n overflow: auto;\n padding: 16px;\n background: ${cssVar.colorBgLayout};\n }\n `,\n search: css`\n display: grid;\n gap: 16px 24px;\n align-items: center;\n `,\n searchActions: css`\n display: flex;\n grid-column-end: -1;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n justify-content: flex-end;\n\n /* Vertical: buttons sit on the control line of the last row (Pro adds a blank label). */\n &[data-layout='vertical'] {\n align-self: end;\n }\n `,\n /* Ellipsis lives on the element that holds the text (Form wraps labels in flex boxes). */\n searchLabelText: css`\n overflow: hidden;\n display: block;\n\n min-width: 0;\n max-width: 100%;\n\n text-overflow: ellipsis;\n white-space: nowrap;\n `,\n searchField: css`\n min-width: 0;\n\n /* The base-ui Form.Field row: no list padding, fixed-width label column, full-width control. */\n & > div {\n gap: 8px;\n padding-block: 0;\n }\n\n & > div > label {\n overflow: hidden;\n flex: none;\n\n width: var(--lobe-pro-table-label-width, auto);\n\n color: ${cssVar.colorTextSecondary};\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n &[data-layout='horizontal'] > div > label {\n text-align: end;\n }\n\n /* A long label never leaves the form: a block label clips and ellipsizes at the END of\n the text (text-align only moves short labels; it never shifts overflow to the start). */\n && > div > label {\n min-width: 0;\n max-width: 100%;\n }\n\n && > div > label * {\n min-width: 0;\n max-width: 100%;\n }\n\n /* Vertical (Pro QueryFilter vertical): label on its own line, full-width control. */\n &[data-layout='vertical'] > div > label {\n width: 100%;\n text-align: start;\n }\n\n & > div > div {\n flex: 1;\n align-items: stretch;\n min-width: 0;\n }\n `,\n searchFieldControl: css`\n flex: 1;\n min-width: 0;\n `,\n searchLabel: css`\n overflow: hidden;\n flex: none;\n\n color: ${cssVar.colorTextSecondary};\n text-align: end;\n text-overflow: ellipsis;\n white-space: nowrap;\n\n &[data-layout='vertical'] {\n text-align: start;\n }\n `,\n setting: css`\n display: flex;\n flex-direction: column;\n\n width: 260px;\n max-height: 420px;\n padding-block: 4px;\n `,\n settingGroupTitle: css`\n padding-block: 6px 2px;\n padding-inline: 12px;\n font-size: ${cssVar.fontSizeSM};\n color: ${cssVar.colorTextDescription};\n `,\n settingHeader: css`\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding-block: 4px 8px;\n padding-inline: 12px;\n border-block-end: 1px solid ${cssVar.colorSplit};\n `,\n settingItem: css`\n display: flex;\n gap: 4px;\n align-items: center;\n\n min-height: 32px;\n padding-inline: 12px 8px;\n\n &:hover {\n background: ${cssVar.colorFillTertiary};\n }\n\n &:hover [data-setting-actions] {\n opacity: 1;\n }\n `,\n settingItemActions: css`\n display: flex;\n flex: none;\n gap: 2px;\n opacity: 0;\n\n &:focus-within {\n opacity: 1;\n }\n `,\n settingItemTitle: css`\n overflow: hidden;\n flex: 1;\n\n min-width: 0;\n\n text-overflow: ellipsis;\n white-space: nowrap;\n `,\n settingList: css`\n overflow: auto;\n flex: 1;\n padding-block: 4px;\n `,\n status: css`\n display: inline-flex;\n gap: 8px;\n align-items: center;\n `,\n statusDot: css`\n flex: none;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n `,\n statusProcessing: css`\n @keyframes lobe-pro-table-status-pulse {\n 0% {\n box-shadow: 0 0 0 0 color-mix(in srgb, currentcolor 40%, transparent);\n }\n\n 100% {\n box-shadow: 0 0 0 4px transparent;\n }\n }\n\n color: ${cssVar.colorPrimary};\n animation: lobe-pro-table-status-pulse 1.2s ease-out infinite;\n `,\n title: css`\n display: flex;\n flex: none;\n gap: 4px;\n align-items: center;\n\n min-width: 0;\n\n font-size: ${cssVar.fontSizeLG};\n font-weight: 600;\n color: ${cssVar.colorText};\n `,\n titleSub: css`\n font-size: ${cssVar.fontSize};\n font-weight: normal;\n color: ${cssVar.colorTextDescription};\n `,\n titleTooltip: css`\n display: inline-flex;\n gap: 4px;\n align-items: center;\n `,\n toolbar: css`\n display: flex;\n flex-wrap: nowrap;\n gap: 12px;\n align-items: center;\n justify-content: space-between;\n\n margin-block-end: 16px;\n `,\n toolbarActions: css`\n display: flex;\n flex: 1;\n flex-wrap: wrap;\n gap: 8px;\n align-items: center;\n justify-content: flex-end;\n\n min-width: 0;\n margin-inline-start: auto;\n `,\n toolbarOptions: css`\n display: flex;\n flex: none;\n gap: 2px;\n align-items: center;\n `,\n}));\n"],"mappings":";;AAEA,MAAa,iBAAiB;AAE9B,MAAa,SAAS,oBAAoB,EAAE,KAAK,cAAc;CAC7D,OAAO,GAAG;;;;;;;;;;qBAUS,OAAO,aAAa;;iBAExB,OAAO,SAAS;aACpB,OAAO,UAAU;;qCAEO,OAAO,aAAa;;CAEvD,WAAW,GAAG;;;;;;;;;CASd,aAAa,GAAG;;;;;;CAMhB,MAAM,GAAG;;;CAGT,cAAc,GAAG;;wBAEK,OAAO,qBAAqB;qBAC/B,OAAO,eAAe;;CAEzC,MAAM,GAAG;;;qBAGU,OAAO,eAAe;;mBAExB,OAAO,eAAe;;;kBAGvB,OAAO,kBAAkB;;CAEzC,UAAU,GAAG;;;;;;CAMb,cAAc,GAAG;;;;;CAKjB,SAAS,GAAG;;;;;;CAMZ,aAAa,GAAG;;;;;;;;;;;qBAWG,OAAO,eAAe;;;aAG9B,OAAO,UAAU;;;;;;;oBAOV,OAAO,kBAAkB;;;;;;;;CAQ3C,UAAU,GAAG;;;;;CAKb,aAAa,GAAG;;;;;;;;;;;;aAYL,OAAO,UAAU;;kBAEZ,OAAO,mBAAmB;;;eAG7B,OAAO,oBAAoB;oBACtB,OAAO,aAAa;;;CAGtC,aAAa,GAAG;;;;;;CAMhB,iBAAiB,GAAG;;;;;;;;;;;;;CAapB,kBAAkB,GAAG;;iBAEN,OAAO,WAAW;aACtB,OAAO,mBAAmB;;;;;;;CAOrC,mBAAmB,GAAG;;;;;CAKtB,YAAY,GAAG;;;;;;;CAOf,MAAM,GAAG;uCAC4B,OAAO,oBAAoB;qCAC7B,OAAO,WAAW;0CACb,OAAO,aAAa;uCACvB,OAAO,aAAa;uCACpB,OAAO,aAAa;;;;;;;;;;;;;;;oBAevC,OAAO,cAAc;;;CAGvC,QAAQ,GAAG;;;;;CAKX,eAAe,GAAG;;;;;;;;;;;;;CAclB,iBAAiB,GAAG;;;;;;;;;;CAUpB,aAAa,GAAG;;;;;;;;;;;;;;;eAeH,OAAO,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCvC,oBAAoB,GAAG;;;;CAIvB,aAAa,GAAG;;;;aAIL,OAAO,mBAAmB;;;;;;;;;CASrC,SAAS,GAAG;;;;;;;;CAQZ,mBAAmB,GAAG;;;iBAGP,OAAO,WAAW;aACtB,OAAO,qBAAqB;;CAEvC,eAAe,GAAG;;;;;;;kCAOc,OAAO,WAAW;;CAElD,aAAa,GAAG;;;;;;;;;oBASE,OAAO,kBAAkB;;;;;;;CAO3C,oBAAoB,GAAG;;;;;;;;;;CAUvB,kBAAkB,GAAG;;;;;;;;;CASrB,aAAa,GAAG;;;;;CAKhB,QAAQ,GAAG;;;;;CAKX,WAAW,GAAG;;;;;;CAMd,kBAAkB,GAAG;;;;;;;;;;;aAWV,OAAO,aAAa;;;CAG/B,OAAO,GAAG;;;;;;;;iBAQK,OAAO,WAAW;;aAEtB,OAAO,UAAU;;CAE5B,UAAU,GAAG;iBACE,OAAO,SAAS;;aAEpB,OAAO,qBAAqB;;CAEvC,cAAc,GAAG;;;;;CAKjB,SAAS,GAAG;;;;;;;;;CASZ,gBAAgB,GAAG;;;;;;;;;;;CAWnB,gBAAgB,GAAG;;;;;;AAMrB,EAAE"}
|
|
@@ -185,13 +185,16 @@ interface ProTableRequestData<T> {
|
|
|
185
185
|
type ProTableRequestSort = Record<string, SortOrder>;
|
|
186
186
|
/** `filter` argument of `request`: column key → selected filter values (ProComponents shape). */
|
|
187
187
|
type ProTableRequestFilter = Record<string, (string | number)[] | null>;
|
|
188
|
-
/**
|
|
188
|
+
/**
|
|
189
|
+
* `request(params, sort, filter)`; resolves `{ data, total, success }` (all optional). A `null` /
|
|
190
|
+
* `undefined` result is treated as empty data.
|
|
191
|
+
*/
|
|
189
192
|
type ProTableRequest<T, Params = Record<string, any>> = (params: Params & {
|
|
190
193
|
[key: string]: any;
|
|
191
194
|
current?: number;
|
|
192
195
|
keyword?: string;
|
|
193
196
|
pageSize?: number;
|
|
194
|
-
}, sort: ProTableRequestSort, filter: ProTableRequestFilter) => Promise<Partial<ProTableRequestData<T
|
|
197
|
+
}, sort: ProTableRequestSort, filter: ProTableRequestFilter) => Promise<Partial<ProTableRequestData<T>> | null | undefined>;
|
|
195
198
|
/**
|
|
196
199
|
* `loading` as an object: Spin options of the table overlay (`tip`, `variant`, …) plus `delay`
|
|
197
200
|
* (ms before the overlay shows). Without `spinning` the overlay follows the `request` state.
|
|
@@ -25,7 +25,7 @@ const useFetchData = (options) => {
|
|
|
25
25
|
params.current = opts.pageInfo.current;
|
|
26
26
|
params.pageSize = opts.pageInfo.pageSize;
|
|
27
27
|
}
|
|
28
|
-
const response = await opts.request(params, opts.sort, opts.filter);
|
|
28
|
+
const response = await opts.request(params, opts.sort, opts.filter) ?? { data: [] };
|
|
29
29
|
if (id !== requestId.current) return;
|
|
30
30
|
if (response.success === false) return;
|
|
31
31
|
const raw = response.data ?? [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFetchData.mjs","names":[],"sources":["../../../src/base-ui/ProTable/useFetchData.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\nimport type { SortOrder } from '@/base-ui/Table/type';\n\nimport type {
|
|
1
|
+
{"version":3,"file":"useFetchData.mjs","names":[],"sources":["../../../src/base-ui/ProTable/useFetchData.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\nimport type { SortOrder } from '@/base-ui/Table/type';\n\nimport type {\n ProTablePageInfo,\n ProTableRequest,\n ProTableRequestData,\n ProTableRequestFilter,\n} from './type';\n\ntype Filter = Record<string, (string | number | boolean)[] | null>;\n\nexport interface UseFetchDataOptions<T> {\n debounceTime: number;\n defaultData?: T[];\n /** Everything except the page that a fetch depends on, as a stable string. */\n depsKey: string;\n filter: Filter;\n getParams: () => Record<string, any>;\n manual: boolean;\n onDataSourceChange?: (data: T[]) => void;\n onLoad?: (data: T[]) => void;\n onLoadingChange?: (loading: boolean) => void;\n onRequestError?: (error: Error) => void;\n pageInfo: ProTablePageInfo;\n paginated: boolean;\n polling?: number | ((data: T[]) => number);\n postData?: (data: T[]) => T[];\n request?: ProTableRequest<T, any>;\n setTotal: (total: number) => void;\n sort: Record<string, SortOrder>;\n}\n\n/** `request` driving: debounced fetch on deps / page change, stale-response guard, polling. */\nexport const useFetchData = <T>(options: UseFetchDataOptions<T>) => {\n const [data, setData] = useState<T[]>(options.defaultData ?? []);\n const [loading, setLoading] = useState(false);\n const latest = useRef(options);\n latest.current = options;\n const requestId = useRef(0);\n const [enabled, setEnabled] = useState(!options.manual);\n const [token, setToken] = useState(0);\n const pending = useRef<(() => void)[]>([]);\n\n const updateLoading = (next: boolean) => {\n setLoading(next);\n latest.current.onLoadingChange?.(next);\n };\n\n const run = useCallback(async () => {\n const opts = latest.current;\n if (!opts.request) return;\n const id = ++requestId.current;\n updateLoading(true);\n try {\n const params: Record<string, any> = { ...opts.getParams() };\n if (opts.paginated) {\n params.current = opts.pageInfo.current;\n params.pageSize = opts.pageInfo.pageSize;\n }\n // A `request` resolving `null` / `undefined` (e.g. an empty API body) is treated as empty data.\n const response: Partial<ProTableRequestData<T>> = (await opts.request(\n params as any,\n opts.sort,\n opts.filter as ProTableRequestFilter,\n )) ?? { data: [] };\n if (id !== requestId.current) return;\n if (response.success === false) {\n // Pro keeps the previous data when the request reports failure.\n return;\n }\n const raw = response.data ?? [];\n const next = opts.postData ? opts.postData(raw) : raw;\n setData(next);\n opts.setTotal(response.total ?? next.length);\n opts.onLoad?.(next);\n opts.onDataSourceChange?.(next);\n } catch (error) {\n if (id !== requestId.current) return;\n if (opts.onRequestError) opts.onRequestError(error as Error);\n else console.error(error);\n } finally {\n if (id === requestId.current) updateLoading(false);\n const resolvers = pending.current;\n pending.current = [];\n resolvers.forEach((resolve) => resolve());\n }\n }, []);\n\n const { current, pageSize } = options.pageInfo;\n useEffect(() => {\n if (!enabled || !latest.current.request) return;\n const delay = latest.current.debounceTime;\n if (delay <= 0) {\n void run();\n return;\n }\n const timer = setTimeout(() => void run(), delay);\n return () => clearTimeout(timer);\n }, [enabled, token, options.depsKey, current, pageSize, run]);\n\n // Polling: schedule the next round once the current one is done.\n useEffect(() => {\n const { polling } = latest.current;\n if (!polling || loading || !enabled) return;\n const interval = typeof polling === 'function' ? polling(data) : polling;\n if (!interval) return;\n const timer = setTimeout(() => void run(), Math.max(interval, 2000));\n return () => clearTimeout(timer);\n }, [data, loading, enabled, options.polling, run]);\n\n /** Force a fetch (also enables a `manualRequest` table); resolves when it settles. */\n const reload = useCallback(\n () =>\n new Promise<void>((resolve) => {\n if (!latest.current.request) {\n resolve();\n return;\n }\n pending.current.push(resolve);\n setEnabled(true);\n setToken((value) => value + 1);\n }),\n [],\n );\n\n return { data, loading, reload, setData };\n};\n"],"mappings":";;;AAmCA,MAAa,gBAAmB,YAAoC;CAClE,MAAM,CAAC,MAAM,WAAW,SAAc,QAAQ,eAAe,CAAC,CAAC;CAC/D,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;CAC5C,MAAM,SAAS,OAAO,OAAO;CAC7B,OAAO,UAAU;CACjB,MAAM,YAAY,OAAO,CAAC;CAC1B,MAAM,CAAC,SAAS,cAAc,SAAS,CAAC,QAAQ,MAAM;CACtD,MAAM,CAAC,OAAO,YAAY,SAAS,CAAC;CACpC,MAAM,UAAU,OAAuB,CAAC,CAAC;CAEzC,MAAM,iBAAiB,SAAkB;EACvC,WAAW,IAAI;EACf,OAAO,QAAQ,kBAAkB,IAAI;CACvC;CAEA,MAAM,MAAM,YAAY,YAAY;EAClC,MAAM,OAAO,OAAO;EACpB,IAAI,CAAC,KAAK,SAAS;EACnB,MAAM,KAAK,EAAE,UAAU;EACvB,cAAc,IAAI;EAClB,IAAI;GACF,MAAM,SAA8B,EAAE,GAAG,KAAK,UAAU,EAAE;GAC1D,IAAI,KAAK,WAAW;IAClB,OAAO,UAAU,KAAK,SAAS;IAC/B,OAAO,WAAW,KAAK,SAAS;GAClC;GAEA,MAAM,WAA6C,MAAM,KAAK,QAC5D,QACA,KAAK,MACL,KAAK,MACP,KAAM,EAAE,MAAM,CAAC,EAAE;GACjB,IAAI,OAAO,UAAU,SAAS;GAC9B,IAAI,SAAS,YAAY,OAEvB;GAEF,MAAM,MAAM,SAAS,QAAQ,CAAC;GAC9B,MAAM,OAAO,KAAK,WAAW,KAAK,SAAS,GAAG,IAAI;GAClD,QAAQ,IAAI;GACZ,KAAK,SAAS,SAAS,SAAS,KAAK,MAAM;GAC3C,KAAK,SAAS,IAAI;GAClB,KAAK,qBAAqB,IAAI;EAChC,SAAS,OAAO;GACd,IAAI,OAAO,UAAU,SAAS;GAC9B,IAAI,KAAK,gBAAgB,KAAK,eAAe,KAAc;QACtD,QAAQ,MAAM,KAAK;EAC1B,UAAU;GACR,IAAI,OAAO,UAAU,SAAS,cAAc,KAAK;GACjD,MAAM,YAAY,QAAQ;GAC1B,QAAQ,UAAU,CAAC;GACnB,UAAU,SAAS,YAAY,QAAQ,CAAC;EAC1C;CACF,GAAG,CAAC,CAAC;CAEL,MAAM,EAAE,SAAS,aAAa,QAAQ;CACtC,gBAAgB;EACd,IAAI,CAAC,WAAW,CAAC,OAAO,QAAQ,SAAS;EACzC,MAAM,QAAQ,OAAO,QAAQ;EAC7B,IAAI,SAAS,GAAG;GACd,IAAS;GACT;EACF;EACA,MAAM,QAAQ,iBAAiB,KAAK,IAAI,GAAG,KAAK;EAChD,aAAa,aAAa,KAAK;CACjC,GAAG;EAAC;EAAS;EAAO,QAAQ;EAAS;EAAS;EAAU;CAAG,CAAC;CAG5D,gBAAgB;EACd,MAAM,EAAE,YAAY,OAAO;EAC3B,IAAI,CAAC,WAAW,WAAW,CAAC,SAAS;EACrC,MAAM,WAAW,OAAO,YAAY,aAAa,QAAQ,IAAI,IAAI;EACjE,IAAI,CAAC,UAAU;EACf,MAAM,QAAQ,iBAAiB,KAAK,IAAI,GAAG,KAAK,IAAI,UAAU,GAAI,CAAC;EACnE,aAAa,aAAa,KAAK;CACjC,GAAG;EAAC;EAAM;EAAS;EAAS,QAAQ;EAAS;CAAG,CAAC;CAiBjD,OAAO;EAAE;EAAM;EAAS,QAdT,kBAEX,IAAI,SAAe,YAAY;GAC7B,IAAI,CAAC,OAAO,QAAQ,SAAS;IAC3B,QAAQ;IACR;GACF;GACA,QAAQ,QAAQ,KAAK,OAAO;GAC5B,WAAW,IAAI;GACf,UAAU,UAAU,QAAQ,CAAC;EAC/B,CAAC,GACH,CAAC,CAG0B;EAAG;CAAQ;AAC1C"}
|
|
@@ -11,10 +11,10 @@ const Switch = memo(({ autoFocus, checked, checkedChildren, className, className
|
|
|
11
11
|
const isDisabled = disabled || loading;
|
|
12
12
|
const resolvedChecked = value ?? checked;
|
|
13
13
|
const resolvedDefaultChecked = defaultValue ?? defaultChecked;
|
|
14
|
+
const hasText = !!(checkedChildren || unCheckedChildren);
|
|
14
15
|
return /* @__PURE__ */ jsxs(SwitchRoot, {
|
|
15
16
|
autoFocus,
|
|
16
17
|
checked: resolvedChecked,
|
|
17
|
-
className: cx(className, rootClassName, classNames?.root),
|
|
18
18
|
defaultChecked: resolvedDefaultChecked,
|
|
19
19
|
disabled: isDisabled,
|
|
20
20
|
id,
|
|
@@ -27,6 +27,7 @@ const Switch = memo(({ autoFocus, checked, checkedChildren, className, className
|
|
|
27
27
|
},
|
|
28
28
|
tabIndex,
|
|
29
29
|
title,
|
|
30
|
+
className: cx(hasText && (size === "small" ? styles.rootTextSmall : styles.rootText), className, rootClassName, classNames?.root),
|
|
30
31
|
onCheckedChange: onChange,
|
|
31
32
|
onClick,
|
|
32
33
|
children: [
|
|
@@ -44,6 +45,11 @@ const Switch = memo(({ autoFocus, checked, checkedChildren, className, className
|
|
|
44
45
|
style: customStyles?.content,
|
|
45
46
|
children: unCheckedChildren
|
|
46
47
|
}),
|
|
48
|
+
hasText && /* @__PURE__ */ jsxs("span", {
|
|
49
|
+
"aria-hidden": true,
|
|
50
|
+
className: cx(styles.textSizer, size === "small" && styles.textSizerSmall),
|
|
51
|
+
children: [/* @__PURE__ */ jsx("span", { children: checkedChildren }), /* @__PURE__ */ jsx("span", { children: unCheckedChildren })]
|
|
52
|
+
}),
|
|
47
53
|
/* @__PURE__ */ jsx(SwitchThumb, {
|
|
48
54
|
className: classNames?.thumb,
|
|
49
55
|
size,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Switch.mjs","names":[],"sources":["../../../src/base-ui/Switch/Switch.tsx"],"sourcesContent":["'use client';\n\nimport { cssVar, cx } from 'antd-style';\nimport { Loader2 } from 'lucide-react';\nimport { memo } from 'react';\n\nimport Icon from '@/Icon';\n\nimport { SwitchIcon, SwitchRoot, SwitchThumb } from './atoms';\nimport { styles } from './style';\nimport type { SwitchProps } from './type';\n\nconst Switch = memo<SwitchProps>(\n ({\n autoFocus,\n checked,\n checkedChildren,\n className,\n classNames,\n defaultChecked,\n defaultValue,\n disabled,\n id,\n loading,\n name,\n onChange,\n onClick,\n ref,\n rootClassName,\n size = 'default',\n style,\n styles: customStyles,\n tabIndex,\n title,\n unCheckedChildren,\n value,\n }) => {\n const isDisabled = disabled || loading;\n const resolvedChecked = value ?? checked;\n const resolvedDefaultChecked = defaultValue ?? defaultChecked;\n\n return (\n <SwitchRoot\n autoFocus={autoFocus}\n checked={resolvedChecked}\n
|
|
1
|
+
{"version":3,"file":"Switch.mjs","names":[],"sources":["../../../src/base-ui/Switch/Switch.tsx"],"sourcesContent":["'use client';\n\nimport { cssVar, cx } from 'antd-style';\nimport { Loader2 } from 'lucide-react';\nimport { memo } from 'react';\n\nimport Icon from '@/Icon';\n\nimport { SwitchIcon, SwitchRoot, SwitchThumb } from './atoms';\nimport { styles } from './style';\nimport type { SwitchProps } from './type';\n\nconst Switch = memo<SwitchProps>(\n ({\n autoFocus,\n checked,\n checkedChildren,\n className,\n classNames,\n defaultChecked,\n defaultValue,\n disabled,\n id,\n loading,\n name,\n onChange,\n onClick,\n ref,\n rootClassName,\n size = 'default',\n style,\n styles: customStyles,\n tabIndex,\n title,\n unCheckedChildren,\n value,\n }) => {\n const isDisabled = disabled || loading;\n const resolvedChecked = value ?? checked;\n const resolvedDefaultChecked = defaultValue ?? defaultChecked;\n\n // With inner text the switch grows to fit it (antd): an invisible sizer reserves the width\n // of the longer label and the thumb travels the measured track.\n const hasText = !!(checkedChildren || unCheckedChildren);\n\n return (\n <SwitchRoot\n autoFocus={autoFocus}\n checked={resolvedChecked}\n defaultChecked={resolvedDefaultChecked}\n disabled={isDisabled}\n id={id}\n name={name}\n ref={ref}\n size={size}\n style={{ ...style, ...customStyles?.root }}\n tabIndex={tabIndex}\n title={title}\n className={cx(\n hasText && (size === 'small' ? styles.rootTextSmall : styles.rootText),\n className,\n rootClassName,\n classNames?.root,\n )}\n onCheckedChange={onChange}\n onClick={onClick}\n >\n {checkedChildren && (\n <SwitchIcon\n className={classNames?.content}\n position=\"left\"\n size={size}\n style={customStyles?.content}\n >\n {checkedChildren}\n </SwitchIcon>\n )}\n {unCheckedChildren && (\n <SwitchIcon\n className={classNames?.content}\n position=\"right\"\n size={size}\n style={customStyles?.content}\n >\n {unCheckedChildren}\n </SwitchIcon>\n )}\n {hasText && (\n <span\n aria-hidden\n className={cx(styles.textSizer, size === 'small' && styles.textSizerSmall)}\n >\n <span>{checkedChildren}</span>\n <span>{unCheckedChildren}</span>\n </span>\n )}\n <SwitchThumb className={classNames?.thumb} size={size} style={customStyles?.thumb}>\n {loading && (\n <Icon\n className={styles.loading}\n icon={Loader2}\n size={size === 'small' ? 8 : 12}\n style={{ color: cssVar.colorPrimary }}\n />\n )}\n </SwitchThumb>\n </SwitchRoot>\n );\n },\n);\n\nSwitch.displayName = 'Switch';\n\nexport default Switch;\n"],"mappings":";;;;;;;;;AAYA,MAAM,SAAS,MACZ,EACC,WACA,SACA,iBACA,WACA,YACA,gBACA,cACA,UACA,IACA,SACA,MACA,UACA,SACA,KACA,eACA,OAAO,WACP,OACA,QAAQ,cACR,UACA,OACA,mBACA,YACI;CACJ,MAAM,aAAa,YAAY;CAC/B,MAAM,kBAAkB,SAAS;CACjC,MAAM,yBAAyB,gBAAgB;CAI/C,MAAM,UAAU,CAAC,EAAE,mBAAmB;CAEtC,OACE,qBAAC,YAAD;EACa;EACX,SAAS;EACT,gBAAgB;EAChB,UAAU;EACN;EACE;EACD;EACC;EACN,OAAO;GAAE,GAAG;GAAO,GAAG,cAAc;EAAK;EAC/B;EACH;EACP,WAAW,GACT,YAAY,SAAS,UAAU,OAAO,gBAAgB,OAAO,WAC7D,WACA,eACA,YAAY,IACd;EACA,iBAAiB;EACR;EAnBX,UAAA;GAqBG,mBACC,oBAAC,YAAD;IACE,WAAW,YAAY;IACvB,UAAS;IACH;IACN,OAAO,cAAc;IAEpB,UAAA;GACS,CAAA;GAEb,qBACC,oBAAC,YAAD;IACE,WAAW,YAAY;IACvB,UAAS;IACH;IACN,OAAO,cAAc;IAEpB,UAAA;GACS,CAAA;GAEb,WACC,qBAAC,QAAD;IACE,eAAA;IACA,WAAW,GAAG,OAAO,WAAW,SAAS,WAAW,OAAO,cAAc;IAF3E,UAAA,CAIE,oBAAC,QAAD,EAAA,UAAO,gBAAsB,CAAA,GAC7B,oBAAC,QAAD,EAAA,UAAO,kBAAwB,CAAA,CAC3B;;GAER,oBAAC,aAAD;IAAa,WAAW,YAAY;IAAa;IAAM,OAAO,cAAc;IACzE,UAAA,WACC,oBAAC,MAAD;KACE,WAAW,OAAO;KAClB,MAAM;KACN,MAAM,SAAS,UAAU,IAAI;KAC7B,OAAO,EAAE,OAAO,OAAO,aAAa;IACrC,CAAA;GAEQ,CAAA;EACH;;AAEhB,CACF;AAEA,OAAO,cAAc"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { rootVariants, styles, thumbVariants } from "./style.mjs";
|
|
3
|
-
import { createContext, use, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
import { createContext, use, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
import { cx } from "antd-style";
|
|
6
6
|
import useMergeState from "use-merge-value";
|
|
@@ -117,7 +117,22 @@ const SwitchThumb = ({ className, size = "default", style, children, ...rest })
|
|
|
117
117
|
const ref = useRef(null);
|
|
118
118
|
const baseClassName = thumbVariants({ size });
|
|
119
119
|
const metrics = THUMB_METRICS[size];
|
|
120
|
-
const
|
|
120
|
+
const [travel, setTravel] = useState(metrics.checkedX);
|
|
121
|
+
useLayoutEffect(() => {
|
|
122
|
+
const root = ref.current?.parentElement;
|
|
123
|
+
if (!root) return;
|
|
124
|
+
const measure = () => {
|
|
125
|
+
const width = root.clientWidth;
|
|
126
|
+
setTravel(width > 0 ? Math.max(metrics.checkedX, width - 4 - metrics.width) : metrics.checkedX);
|
|
127
|
+
};
|
|
128
|
+
measure();
|
|
129
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
130
|
+
const observer = new ResizeObserver(measure);
|
|
131
|
+
observer.observe(root);
|
|
132
|
+
return () => observer.disconnect();
|
|
133
|
+
}, [metrics]);
|
|
134
|
+
const extra = travel - metrics.checkedX;
|
|
135
|
+
const targetX = isChecked ? (isPressed ? metrics.pressedCheckedX : metrics.checkedX) + extra : 0;
|
|
121
136
|
const targetWidth = isPressed ? metrics.pressedWidth : metrics.width;
|
|
122
137
|
const [values] = useState(() => ({
|
|
123
138
|
width: motionValue(targetWidth),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atoms.mjs","names":["useControlledState"],"sources":["../../../src/base-ui/Switch/atoms.tsx"],"sourcesContent":["'use client';\n\nimport { Switch } from '@base-ui/react/switch';\nimport { cx } from 'antd-style';\nimport { animate, motionValue } from 'motion';\nimport type { CSSProperties, KeyboardEvent, MouseEvent, PointerEvent } from 'react';\nimport { createContext, use, useEffect, useMemo, useRef, useState } from 'react';\nimport useControlledState from 'use-merge-value';\n\nimport { rootVariants, styles, thumbVariants } from './style';\nimport type {\n SwitchChangeEventHandler,\n SwitchContextType,\n SwitchIconPosition,\n SwitchIconProps,\n SwitchRootProps,\n SwitchSize,\n SwitchThumbProps,\n} from './type';\n\nconst THUMB_METRICS: Record<\n SwitchSize,\n { checkedX: number; pressedCheckedX: number; pressedWidth: number; width: number }\n> = {\n default: { checkedX: 14, pressedCheckedX: 10, pressedWidth: 22, width: 18 },\n small: { checkedX: 12, pressedCheckedX: 8, pressedWidth: 16, width: 12 },\n};\n\nconst THUMB_SPRING = { damping: 24, stiffness: 360, type: 'spring' as const };\n\nconst SwitchContext = createContext<SwitchContextType | null>(null);\n\nexport const useSwitchContext = () => {\n const context = use(SwitchContext);\n if (!context) {\n throw new Error('useSwitchContext must be used within a SwitchRoot');\n }\n return context;\n};\n\ntype SwitchRootInternalProps = Omit<SwitchRootProps, 'onCheckedChange' | 'onClick'> & {\n onCheckedChange?: SwitchChangeEventHandler;\n onClick?: SwitchChangeEventHandler;\n};\n\nexport const SwitchRoot = ({\n checked,\n className,\n defaultChecked,\n onCheckedChange,\n onClick,\n onKeyDown,\n onKeyUp,\n onPointerCancel,\n onPointerDown,\n onPointerLeave,\n onPointerUp,\n size = 'default',\n children,\n disabled,\n readOnly,\n required,\n inputRef,\n id,\n name,\n ...rest\n}: SwitchRootInternalProps) => {\n const [isPressed, setIsPressed] = useState(false);\n const lastEventRef = useRef<MouseEvent<HTMLButtonElement> | KeyboardEvent<HTMLButtonElement>>(\n null,\n );\n\n const [isChecked, setIsChecked] = useControlledState(defaultChecked ?? false, {\n defaultValue: defaultChecked,\n onChange: (value: boolean) => {\n if (lastEventRef.current) {\n onCheckedChange?.(value, lastEventRef.current);\n }\n },\n value: checked,\n });\n\n const baseClassName = rootVariants({ size });\n\n const contextValue = useMemo(\n () => ({\n isChecked: Boolean(isChecked),\n isPressed,\n setIsChecked: (value: boolean) => setIsChecked(value),\n setIsPressed,\n }),\n [isChecked, isPressed, setIsChecked],\n );\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n lastEventRef.current = event;\n onClick?.(!isChecked, event);\n };\n\n const isInteractive = !disabled && !readOnly;\n\n const handleKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n if (event.key === 'Enter' || event.key === ' ') {\n lastEventRef.current = event;\n }\n if (event.key === ' ' && isInteractive) {\n setIsPressed(true);\n }\n onKeyDown?.(event);\n };\n\n const handleKeyUp = (event: KeyboardEvent<HTMLButtonElement>) => {\n if (event.key === ' ') {\n setIsPressed(false);\n }\n onKeyUp?.(event);\n };\n\n const handlePointerDown = (event: PointerEvent<HTMLButtonElement>) => {\n if (isInteractive) {\n setIsPressed(true);\n }\n onPointerDown?.(event);\n };\n\n const handlePointerUp = (event: PointerEvent<HTMLButtonElement>) => {\n setIsPressed(false);\n onPointerUp?.(event);\n };\n\n const handlePointerCancel = (event: PointerEvent<HTMLButtonElement>) => {\n setIsPressed(false);\n onPointerCancel?.(event);\n };\n\n const handlePointerLeave = (event: PointerEvent<HTMLButtonElement>) => {\n setIsPressed(false);\n onPointerLeave?.(event);\n };\n\n return (\n <SwitchContext value={contextValue}>\n <Switch.Root\n nativeButton\n checked={isChecked}\n defaultChecked={defaultChecked}\n disabled={disabled}\n id={id}\n inputRef={inputRef}\n name={name}\n readOnly={readOnly}\n required={required}\n render={\n <button\n {...rest}\n className={cx(baseClassName, className)}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n onPointerCancel={handlePointerCancel}\n onPointerDown={handlePointerDown}\n onPointerLeave={handlePointerLeave}\n onPointerUp={handlePointerUp}\n />\n }\n onCheckedChange={setIsChecked}\n >\n {children}\n </Switch.Root>\n </SwitchContext>\n );\n};\n\nSwitchRoot.displayName = 'SwitchRoot';\n\nexport const SwitchThumb = ({\n className,\n size = 'default',\n style,\n children,\n ...rest\n}: SwitchThumbProps) => {\n const { isChecked, isPressed } = useSwitchContext();\n const ref = useRef<HTMLSpanElement>(null);\n const baseClassName = thumbVariants({ size });\n\n const metrics = THUMB_METRICS[size];\n const targetX = isChecked ? (isPressed ? metrics.pressedCheckedX : metrics.checkedX) : 0;\n const targetWidth = isPressed ? metrics.pressedWidth : metrics.width;\n\n const [values] = useState(() => ({\n width: motionValue(targetWidth),\n x: motionValue(targetX),\n }));\n\n // animated keys stay referentially stable so React never rewrites mid-flight inline values\n const [initialStyle] = useState<CSSProperties>(\n () => ({ '--switch-x': `${targetX}px`, 'width': targetWidth }) as CSSProperties,\n );\n\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const unsubscribeX = values.x.on('change', (x) => {\n el.style.setProperty('--switch-x', `${x}px`);\n });\n const unsubscribeWidth = values.width.on('change', (width) => {\n el.style.setProperty('width', `${width}px`);\n });\n return () => {\n unsubscribeX();\n unsubscribeWidth();\n };\n }, [values]);\n\n useEffect(() => {\n const reduceMotion = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;\n const transition = reduceMotion ? { duration: 0 } : THUMB_SPRING;\n const animations = [\n animate(values.x, targetX, transition),\n animate(values.width, targetWidth, transition),\n ];\n return () => {\n for (const animation of animations) animation.stop();\n };\n }, [values, targetX, targetWidth]);\n\n return (\n <Switch.Thumb\n render={\n <span\n {...rest}\n className={cx(baseClassName, className)}\n ref={ref}\n style={{ ...initialStyle, ...style }}\n >\n {children}\n </span>\n }\n />\n );\n};\n\nSwitchThumb.displayName = 'SwitchThumb';\n\nconst getIconPositionClass = (position: SwitchIconPosition, size: 'default' | 'small') => {\n if (position === 'thumb') return styles.iconThumb;\n if (position === 'left') return size === 'small' ? styles.iconLeftSmall : styles.iconLeft;\n return size === 'small' ? styles.iconRightSmall : styles.iconRight;\n};\n\nexport const SwitchIcon = ({\n children,\n className,\n position,\n size = 'default',\n ...rest\n}: SwitchIconProps) => {\n const positionClass = getIconPositionClass(position, size);\n\n return (\n <span className={cx(styles.icon, positionClass, className)} {...rest}>\n {children}\n </span>\n );\n};\n\nSwitchIcon.displayName = 'SwitchIcon';\n\nexport { styles as switchStyles } from './style';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"atoms.mjs","names":["useControlledState"],"sources":["../../../src/base-ui/Switch/atoms.tsx"],"sourcesContent":["'use client';\n\nimport { Switch } from '@base-ui/react/switch';\nimport { cx } from 'antd-style';\nimport { animate, motionValue } from 'motion';\nimport type { CSSProperties, KeyboardEvent, MouseEvent, PointerEvent } from 'react';\nimport { createContext, use, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport useControlledState from 'use-merge-value';\n\nimport { rootVariants, styles, thumbVariants } from './style';\nimport type {\n SwitchChangeEventHandler,\n SwitchContextType,\n SwitchIconPosition,\n SwitchIconProps,\n SwitchRootProps,\n SwitchSize,\n SwitchThumbProps,\n} from './type';\n\nconst THUMB_METRICS: Record<\n SwitchSize,\n { checkedX: number; pressedCheckedX: number; pressedWidth: number; width: number }\n> = {\n default: { checkedX: 14, pressedCheckedX: 10, pressedWidth: 22, width: 18 },\n small: { checkedX: 12, pressedCheckedX: 8, pressedWidth: 16, width: 12 },\n};\n\nconst THUMB_SPRING = { damping: 24, stiffness: 360, type: 'spring' as const };\n\nconst SwitchContext = createContext<SwitchContextType | null>(null);\n\nexport const useSwitchContext = () => {\n const context = use(SwitchContext);\n if (!context) {\n throw new Error('useSwitchContext must be used within a SwitchRoot');\n }\n return context;\n};\n\ntype SwitchRootInternalProps = Omit<SwitchRootProps, 'onCheckedChange' | 'onClick'> & {\n onCheckedChange?: SwitchChangeEventHandler;\n onClick?: SwitchChangeEventHandler;\n};\n\nexport const SwitchRoot = ({\n checked,\n className,\n defaultChecked,\n onCheckedChange,\n onClick,\n onKeyDown,\n onKeyUp,\n onPointerCancel,\n onPointerDown,\n onPointerLeave,\n onPointerUp,\n size = 'default',\n children,\n disabled,\n readOnly,\n required,\n inputRef,\n id,\n name,\n ...rest\n}: SwitchRootInternalProps) => {\n const [isPressed, setIsPressed] = useState(false);\n const lastEventRef = useRef<MouseEvent<HTMLButtonElement> | KeyboardEvent<HTMLButtonElement>>(\n null,\n );\n\n const [isChecked, setIsChecked] = useControlledState(defaultChecked ?? false, {\n defaultValue: defaultChecked,\n onChange: (value: boolean) => {\n if (lastEventRef.current) {\n onCheckedChange?.(value, lastEventRef.current);\n }\n },\n value: checked,\n });\n\n const baseClassName = rootVariants({ size });\n\n const contextValue = useMemo(\n () => ({\n isChecked: Boolean(isChecked),\n isPressed,\n setIsChecked: (value: boolean) => setIsChecked(value),\n setIsPressed,\n }),\n [isChecked, isPressed, setIsChecked],\n );\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n lastEventRef.current = event;\n onClick?.(!isChecked, event);\n };\n\n const isInteractive = !disabled && !readOnly;\n\n const handleKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n if (event.key === 'Enter' || event.key === ' ') {\n lastEventRef.current = event;\n }\n if (event.key === ' ' && isInteractive) {\n setIsPressed(true);\n }\n onKeyDown?.(event);\n };\n\n const handleKeyUp = (event: KeyboardEvent<HTMLButtonElement>) => {\n if (event.key === ' ') {\n setIsPressed(false);\n }\n onKeyUp?.(event);\n };\n\n const handlePointerDown = (event: PointerEvent<HTMLButtonElement>) => {\n if (isInteractive) {\n setIsPressed(true);\n }\n onPointerDown?.(event);\n };\n\n const handlePointerUp = (event: PointerEvent<HTMLButtonElement>) => {\n setIsPressed(false);\n onPointerUp?.(event);\n };\n\n const handlePointerCancel = (event: PointerEvent<HTMLButtonElement>) => {\n setIsPressed(false);\n onPointerCancel?.(event);\n };\n\n const handlePointerLeave = (event: PointerEvent<HTMLButtonElement>) => {\n setIsPressed(false);\n onPointerLeave?.(event);\n };\n\n return (\n <SwitchContext value={contextValue}>\n <Switch.Root\n nativeButton\n checked={isChecked}\n defaultChecked={defaultChecked}\n disabled={disabled}\n id={id}\n inputRef={inputRef}\n name={name}\n readOnly={readOnly}\n required={required}\n render={\n <button\n {...rest}\n className={cx(baseClassName, className)}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n onPointerCancel={handlePointerCancel}\n onPointerDown={handlePointerDown}\n onPointerLeave={handlePointerLeave}\n onPointerUp={handlePointerUp}\n />\n }\n onCheckedChange={setIsChecked}\n >\n {children}\n </Switch.Root>\n </SwitchContext>\n );\n};\n\nSwitchRoot.displayName = 'SwitchRoot';\n\nexport const SwitchThumb = ({\n className,\n size = 'default',\n style,\n children,\n ...rest\n}: SwitchThumbProps) => {\n const { isChecked, isPressed } = useSwitchContext();\n const ref = useRef<HTMLSpanElement>(null);\n const baseClassName = thumbVariants({ size });\n\n const metrics = THUMB_METRICS[size];\n // Track travel: the fixed metric, or the measured width when the root grows (inner text).\n const [travel, setTravel] = useState(metrics.checkedX);\n useLayoutEffect(() => {\n const root = ref.current?.parentElement;\n if (!root) return;\n const measure = () => {\n const width = root.clientWidth;\n // root padding 2px each side\n setTravel(\n width > 0 ? Math.max(metrics.checkedX, width - 4 - metrics.width) : metrics.checkedX,\n );\n };\n measure();\n if (typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(measure);\n observer.observe(root);\n return () => observer.disconnect();\n }, [metrics]);\n const extra = travel - metrics.checkedX;\n const targetX = isChecked ? (isPressed ? metrics.pressedCheckedX : metrics.checkedX) + extra : 0;\n const targetWidth = isPressed ? metrics.pressedWidth : metrics.width;\n\n const [values] = useState(() => ({\n width: motionValue(targetWidth),\n x: motionValue(targetX),\n }));\n\n // animated keys stay referentially stable so React never rewrites mid-flight inline values\n const [initialStyle] = useState<CSSProperties>(\n () => ({ '--switch-x': `${targetX}px`, 'width': targetWidth }) as CSSProperties,\n );\n\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const unsubscribeX = values.x.on('change', (x) => {\n el.style.setProperty('--switch-x', `${x}px`);\n });\n const unsubscribeWidth = values.width.on('change', (width) => {\n el.style.setProperty('width', `${width}px`);\n });\n return () => {\n unsubscribeX();\n unsubscribeWidth();\n };\n }, [values]);\n\n useEffect(() => {\n const reduceMotion = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;\n const transition = reduceMotion ? { duration: 0 } : THUMB_SPRING;\n const animations = [\n animate(values.x, targetX, transition),\n animate(values.width, targetWidth, transition),\n ];\n return () => {\n for (const animation of animations) animation.stop();\n };\n }, [values, targetX, targetWidth]);\n\n return (\n <Switch.Thumb\n render={\n <span\n {...rest}\n className={cx(baseClassName, className)}\n ref={ref}\n style={{ ...initialStyle, ...style }}\n >\n {children}\n </span>\n }\n />\n );\n};\n\nSwitchThumb.displayName = 'SwitchThumb';\n\nconst getIconPositionClass = (position: SwitchIconPosition, size: 'default' | 'small') => {\n if (position === 'thumb') return styles.iconThumb;\n if (position === 'left') return size === 'small' ? styles.iconLeftSmall : styles.iconLeft;\n return size === 'small' ? styles.iconRightSmall : styles.iconRight;\n};\n\nexport const SwitchIcon = ({\n children,\n className,\n position,\n size = 'default',\n ...rest\n}: SwitchIconProps) => {\n const positionClass = getIconPositionClass(position, size);\n\n return (\n <span className={cx(styles.icon, positionClass, className)} {...rest}>\n {children}\n </span>\n );\n};\n\nSwitchIcon.displayName = 'SwitchIcon';\n\nexport { styles as switchStyles } from './style';\n"],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
14
14
|
justify-content: center;
|
|
15
15
|
|
|
16
16
|
color: ${cssVar.colorBgLayout};
|
|
17
|
+
white-space: nowrap;
|
|
17
18
|
|
|
18
19
|
transition:
|
|
19
20
|
opacity 200ms ${cssVar.motionEaseOut},
|
|
@@ -24,7 +25,7 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
24
25
|
}
|
|
25
26
|
`,
|
|
26
27
|
iconLeft: css`
|
|
27
|
-
inset-inline-start:
|
|
28
|
+
inset-inline-start: 7px;
|
|
28
29
|
scale: 0;
|
|
29
30
|
opacity: 0;
|
|
30
31
|
|
|
@@ -44,7 +45,7 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
44
45
|
}
|
|
45
46
|
`,
|
|
46
47
|
iconRight: css`
|
|
47
|
-
inset-inline-end:
|
|
48
|
+
inset-inline-end: 7px;
|
|
48
49
|
|
|
49
50
|
[data-checked] & {
|
|
50
51
|
scale: 0;
|
|
@@ -144,6 +145,50 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
144
145
|
width: 36px;
|
|
145
146
|
min-width: 36px;
|
|
146
147
|
height: 22px;
|
|
148
|
+
`,
|
|
149
|
+
rootText: css`
|
|
150
|
+
width: auto;
|
|
151
|
+
min-width: 44px;
|
|
152
|
+
font-size: 12px;
|
|
153
|
+
line-height: 1;
|
|
154
|
+
|
|
155
|
+
& > :last-child {
|
|
156
|
+
position: absolute;
|
|
157
|
+
inset-inline-start: 2px;
|
|
158
|
+
}
|
|
159
|
+
`,
|
|
160
|
+
rootTextSmall: css`
|
|
161
|
+
width: auto;
|
|
162
|
+
min-width: 32px;
|
|
163
|
+
font-size: 10px;
|
|
164
|
+
line-height: 1;
|
|
165
|
+
|
|
166
|
+
& > :last-child {
|
|
167
|
+
position: absolute;
|
|
168
|
+
inset-inline-start: 2px;
|
|
169
|
+
}
|
|
170
|
+
`,
|
|
171
|
+
textSizer: css`
|
|
172
|
+
pointer-events: none;
|
|
173
|
+
|
|
174
|
+
display: grid;
|
|
175
|
+
flex: none;
|
|
176
|
+
order: 1;
|
|
177
|
+
|
|
178
|
+
/* thumb slot (18px) + gaps */
|
|
179
|
+
padding-inline: 24px 4px;
|
|
180
|
+
|
|
181
|
+
white-space: nowrap;
|
|
182
|
+
|
|
183
|
+
visibility: hidden;
|
|
184
|
+
|
|
185
|
+
& > * {
|
|
186
|
+
grid-area: 1 / 1;
|
|
187
|
+
}
|
|
188
|
+
`,
|
|
189
|
+
textSizerSmall: css`
|
|
190
|
+
/* thumb slot (12px) + gaps */
|
|
191
|
+
padding-inline: 16px 2px;
|
|
147
192
|
`,
|
|
148
193
|
rootSmall: css`
|
|
149
194
|
width: 28px;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.mjs","names":[],"sources":["../../../src/base-ui/Switch/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\nimport { cva } from 'class-variance-authority';\n\nimport { focusRing } from '@/base-ui/focusRing';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n icon: css`\n pointer-events: none;\n\n position: absolute;\n inset-block: 0;\n\n display: flex;\n align-items: center;\n justify-content: center;\n\n color: ${cssVar.colorBgLayout};\n\n transition:\n opacity 200ms ${cssVar.motionEaseOut},\n scale 200ms ${cssVar.motionEaseOut};\n\n @media (prefers-reduced-motion: reduce) {\n transition-duration: 0s;\n }\n `,\n iconLeft: css`\n inset-inline-start:
|
|
1
|
+
{"version":3,"file":"style.mjs","names":[],"sources":["../../../src/base-ui/Switch/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\nimport { cva } from 'class-variance-authority';\n\nimport { focusRing } from '@/base-ui/focusRing';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n icon: css`\n pointer-events: none;\n\n position: absolute;\n inset-block: 0;\n\n display: flex;\n align-items: center;\n justify-content: center;\n\n color: ${cssVar.colorBgLayout};\n white-space: nowrap;\n\n transition:\n opacity 200ms ${cssVar.motionEaseOut},\n scale 200ms ${cssVar.motionEaseOut};\n\n @media (prefers-reduced-motion: reduce) {\n transition-duration: 0s;\n }\n `,\n iconLeft: css`\n inset-inline-start: 7px;\n scale: 0;\n opacity: 0;\n\n [data-checked] & {\n scale: 1;\n opacity: 1;\n }\n `,\n iconLeftSmall: css`\n inset-inline-start: 4px;\n scale: 0;\n opacity: 0;\n\n [data-checked] & {\n scale: 1;\n opacity: 1;\n }\n `,\n iconRight: css`\n inset-inline-end: 7px;\n\n [data-checked] & {\n scale: 0;\n opacity: 0;\n }\n `,\n iconRightSmall: css`\n inset-inline-end: 4px;\n\n [data-checked] & {\n scale: 0;\n opacity: 0;\n }\n `,\n iconThumb: css`\n position: relative;\n inset: unset;\n transform: none;\n color: ${cssVar.colorPrimary};\n `,\n loading: css`\n @keyframes lobe-switch-loading {\n 0% {\n transform: rotate(0deg);\n }\n\n 100% {\n transform: rotate(360deg);\n }\n }\n\n animation: lobe-switch-loading 1s linear infinite;\n\n @media (prefers-reduced-motion: reduce) {\n animation-duration: 0s;\n }\n `,\n root: css`\n --switch-dir: 1;\n\n cursor: pointer;\n user-select: none;\n\n position: relative;\n\n overflow: hidden;\n display: inline-flex;\n align-items: center;\n justify-content: flex-start;\n\n box-sizing: border-box;\n padding: 2px;\n border: 0;\n border-radius: 100px;\n\n background: ${cssVar.colorFillSecondary};\n outline: none;\n box-shadow: inset 0 1.5px 2px rgb(0 0 0 / 8%);\n\n transition:\n background 200ms ${cssVar.motionEaseOut},\n box-shadow 200ms ${cssVar.motionEaseOut};\n\n &:dir(rtl) {\n --switch-dir: -1;\n }\n\n [dir='rtl'] & {\n --switch-dir: -1;\n }\n\n ${focusRing};\n\n &:hover:not([data-disabled]) {\n background: ${cssVar.colorFill};\n }\n\n &[data-checked] {\n background: ${cssVar.colorPrimary};\n box-shadow: inset 0 1.5px 3px rgb(0 0 0 / 18%);\n\n &:hover:not([data-disabled]) {\n background: ${cssVar.colorPrimaryHover};\n }\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n opacity: 0.45;\n }\n\n @media (prefers-reduced-motion: reduce) {\n transition-duration: 0s;\n }\n `,\n rootDefault: css`\n width: 36px;\n min-width: 36px;\n height: 22px;\n `,\n /* Text mode: the root sizes to the sizer only. The thumb is taken out of flow (its press\n animation widens it) so pressing never resizes the control; the sizer reserves its slot. */\n rootText: css`\n width: auto;\n min-width: 44px;\n font-size: 12px;\n line-height: 1;\n\n & > :last-child {\n position: absolute;\n inset-inline-start: 2px;\n }\n `,\n rootTextSmall: css`\n width: auto;\n min-width: 32px;\n font-size: 10px;\n line-height: 1;\n\n & > :last-child {\n position: absolute;\n inset-inline-start: 2px;\n }\n `,\n textSizer: css`\n pointer-events: none;\n\n display: grid;\n flex: none;\n order: 1;\n\n /* thumb slot (18px) + gaps */\n padding-inline: 24px 4px;\n\n white-space: nowrap;\n\n visibility: hidden;\n\n & > * {\n grid-area: 1 / 1;\n }\n `,\n textSizerSmall: css`\n /* thumb slot (12px) + gaps */\n padding-inline: 16px 2px;\n `,\n rootSmall: css`\n width: 28px;\n min-width: 28px;\n height: 16px;\n `,\n thumb: css`\n transform: translateX(calc(var(--switch-x, 0px) * var(--switch-dir, 1)));\n\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n border-radius: 50%;\n\n background: ${cssVar.colorBgContainer};\n box-shadow:\n 0 0 0 0.5px rgb(0 0 0 / 4%),\n 0 1px 1px rgb(0 0 0 / 6%),\n 0 3px 8px rgb(0 30 80 / 16%);\n\n transition: box-shadow 200ms ${cssVar.motionEaseOut};\n\n [role='switch']:hover:not([data-disabled]) > & {\n box-shadow:\n 0 0 0 0.5px rgb(0 0 0 / 4%),\n 0 1px 1px rgb(0 0 0 / 8%),\n 0 6px 14px rgb(0 30 80 / 24%);\n }\n\n [data-disabled] > & {\n box-shadow: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n transition-duration: 0s;\n }\n `,\n thumbDefault: css`\n width: 18px;\n height: 18px;\n `,\n thumbSmall: css`\n width: 12px;\n height: 12px;\n `,\n}));\n\nexport const rootVariants = cva(styles.root, {\n defaultVariants: {\n size: 'default',\n },\n variants: {\n size: {\n default: styles.rootDefault,\n small: styles.rootSmall,\n },\n },\n});\n\nexport const thumbVariants = cva(styles.thumb, {\n defaultVariants: {\n size: 'default',\n },\n variants: {\n size: {\n default: styles.thumbDefault,\n small: styles.thumbSmall,\n },\n },\n});\n"],"mappings":";;;;AAKA,MAAa,SAAS,oBAAoB,EAAE,KAAK,cAAc;CAC7D,MAAM,GAAG;;;;;;;;;;aAUE,OAAO,cAAc;;;;sBAIZ,OAAO,cAAc;oBACvB,OAAO,cAAc;;;;;;CAMvC,UAAU,GAAG;;;;;;;;;;CAUb,eAAe,GAAG;;;;;;;;;;CAUlB,WAAW,GAAG;;;;;;;;CAQd,gBAAgB,GAAG;;;;;;;;CAQnB,WAAW,GAAG;;;;aAIH,OAAO,aAAa;;CAE/B,SAAS,GAAG;;;;;;;;;;;;;;;;;CAiBZ,MAAM,GAAG;;;;;;;;;;;;;;;;;;kBAkBO,OAAO,mBAAmB;;;;;yBAKnB,OAAO,cAAc;yBACrB,OAAO,cAAc;;;;;;;;;;MAUxC,UAAU;;;oBAGI,OAAO,UAAU;;;;oBAIjB,OAAO,aAAa;;;;sBAIlB,OAAO,kBAAkB;;;;;;;;;;;;;CAa7C,aAAa,GAAG;;;;;CAOhB,UAAU,GAAG;;;;;;;;;;;CAWb,eAAe,GAAG;;;;;;;;;;;CAWlB,WAAW,GAAG;;;;;;;;;;;;;;;;;;CAkBd,gBAAgB,GAAG;;;;CAInB,WAAW,GAAG;;;;;CAKd,OAAO,GAAG;;;;;;;;;;kBAUM,OAAO,iBAAiB;;;;;;mCAMP,OAAO,cAAc;;;;;;;;;;;;;;;;;CAiBtD,cAAc,GAAG;;;;CAIjB,YAAY,GAAG;;;;AAIjB,EAAE;AAEF,MAAa,eAAe,IAAI,OAAO,MAAM;CAC3C,iBAAiB,EACf,MAAM,UACR;CACA,UAAU,EACR,MAAM;EACJ,SAAS,OAAO;EAChB,OAAO,OAAO;CAChB,EACF;AACF,CAAC;AAED,MAAa,gBAAgB,IAAI,OAAO,OAAO;CAC7C,iBAAiB,EACf,MAAM,UACR;CACA,UAAU,EACR,MAAM;EACJ,SAAS,OAAO;EAChB,OAAO,OAAO;CAChB,EACF;AACF,CAAC"}
|
|
@@ -20,13 +20,20 @@ const measureSides = (rows) => {
|
|
|
20
20
|
const collectRails = (table) => {
|
|
21
21
|
const rails = [];
|
|
22
22
|
const own = (el) => el.closest(p) === table;
|
|
23
|
+
const ownMatch = (selector) => Array.from(table.querySelectorAll(selector)).some((el) => own(el));
|
|
24
|
+
if (ownMatch(`${p}-placeholder`) || ownMatch("[data-table-skeleton]")) return rails;
|
|
25
|
+
const showStart = ownMatch(`.${PREFIX_CLS}-cell-fix-start-shadow-show`);
|
|
26
|
+
const showEnd = ownMatch(`.${PREFIX_CLS}-cell-fix-end-shadow-show`);
|
|
27
|
+
if (!showStart && !showEnd) return rails;
|
|
23
28
|
const hosts = table.querySelectorAll(`${p}-content, ${p}-header, ${p}-body, ${p}-tbody-virtual-holder-inner`);
|
|
24
29
|
for (const host of Array.from(hosts)) {
|
|
25
30
|
if (!own(host)) continue;
|
|
26
31
|
if (host.closest(`${p}-sticky-holder`)) continue;
|
|
27
32
|
if (host.classList.contains(`lobe-table-tbody-virtual-holder-inner`)) {
|
|
28
33
|
const rows = Array.from(host.children).filter((el) => el.classList.contains(`lobe-table-row`) && !el.classList.contains(`lobe-table-row-extra`));
|
|
29
|
-
const
|
|
34
|
+
const measured = measureSides(rows.slice(0, 3));
|
|
35
|
+
const start = showStart ? measured.start : 0;
|
|
36
|
+
const end = showEnd ? measured.end : 0;
|
|
30
37
|
if (start || end) rails.push({
|
|
31
38
|
end,
|
|
32
39
|
fill: true,
|
|
@@ -40,7 +47,9 @@ const collectRails = (table) => {
|
|
|
40
47
|
const tableEl = host.querySelector(":scope > table");
|
|
41
48
|
if (!tableEl) continue;
|
|
42
49
|
const rows = Array.from(tableEl.querySelectorAll(":scope > thead > tr, :scope > tbody > tr")).filter((row) => !row.classList.contains(`${PREFIX_CLS}-measure-row`)).slice(0, 6);
|
|
43
|
-
const
|
|
50
|
+
const measured = measureSides(rows);
|
|
51
|
+
const start = showStart ? measured.start : 0;
|
|
52
|
+
const end = showEnd ? measured.end : 0;
|
|
44
53
|
if (!start && !end) continue;
|
|
45
54
|
rails.push({
|
|
46
55
|
end,
|
|
@@ -61,6 +70,10 @@ const sameRails = (a, b) => a.length === b.length && a.every((rail, i) => rail.h
|
|
|
61
70
|
* row layer) and holds two sticky panes spanning the fixed-start / fixed-end width and the
|
|
62
71
|
* full height. The rail sits at z-index 1: above the scrolling cells (z auto), below the
|
|
63
72
|
* fixed cells (z >= 2), so their dividers and content stay sharp on top of the blur.
|
|
73
|
+
* A side is only frosted while content is scrolled under it, never for an empty / skeleton
|
|
74
|
+
* body (empty / loading skeleton), so row dividers stay continuous through fixed columns.
|
|
75
|
+
* With rows and `loading` the rail stays (below the fixed cells and their dividers) so the
|
|
76
|
+
* scrolled content does not show through the see-through fixed cells under the mask.
|
|
64
77
|
*/
|
|
65
78
|
const FixedFrost = memo(({ rootRef }) => {
|
|
66
79
|
const [rails, setRails] = useState([]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FixedFrost.mjs","names":[],"sources":["../../../src/base-ui/Table/FixedFrost.tsx"],"sourcesContent":["'use client';\n\nimport { memo, type RefObject, useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { PREFIX_CLS, styles } from './style';\n\nconst p = `.${PREFIX_CLS}`;\n\ninterface Rail {\n end: number;\n /** Table hosts size the rail to the table; the virtual body fills its row layer. */\n fill: boolean;\n height: number;\n host: HTMLElement;\n start: number;\n width: number;\n}\n\nconst px = (value: string) => Number.parseFloat(value) || 0;\n\n/** Widths of the fixed-start / fixed-end blocks: max sticky offset + cell width over the rows. */\nconst measureSides = (rows: Element[]) => {\n let start = 0;\n let end = 0;\n for (const row of rows) {\n for (const cell of Array.from(row.children) as HTMLElement[]) {\n if (cell.classList.contains(`${PREFIX_CLS}-cell-fix-start`)) {\n start = Math.max(\n start,\n px(cell.style.insetInlineStart || cell.style.left) + cell.offsetWidth,\n );\n } else if (cell.classList.contains(`${PREFIX_CLS}-cell-fix-end`)) {\n end = Math.max(end, px(cell.style.insetInlineEnd || cell.style.right) + cell.offsetWidth);\n }\n }\n }\n return { end: Math.round(end), start: Math.round(start) };\n};\n\nconst collectRails = (table: HTMLElement): Rail[] => {\n const rails: Rail[] = [];\n const own = (el: Element) => el.closest(p) === table;\n const hosts = table.querySelectorAll<HTMLElement>(\n `${p}-content, ${p}-header, ${p}-body, ${p}-tbody-virtual-holder-inner`,\n );\n\n for (const host of Array.from(hosts)) {\n if (!own(host)) continue;\n // A sticky header is frosted as one element by CSS (it is a backdrop root anyway).\n if (host.closest(`${p}-sticky-holder`)) continue;\n\n if (host.classList.contains(`${PREFIX_CLS}-tbody-virtual-holder-inner`)) {\n const rows = Array.from(host.children).filter(\n (el) =>\n el.classList.contains(`${PREFIX_CLS}-row`) &&\n !el.classList.contains(`${PREFIX_CLS}-row-extra`),\n );\n const { start, end } = measureSides(rows.slice(0, 3));\n if (start || end) rails.push({ end, fill: true, height: 0, host, start, width: 0 });\n continue;\n }\n\n const tableEl = host.querySelector<HTMLTableElement>(':scope > table');\n if (!tableEl) continue;\n const rows = Array.from(tableEl.querySelectorAll(':scope > thead > tr, :scope > tbody > tr'))\n .filter((row) => !row.classList.contains(`${PREFIX_CLS}-measure-row`))\n .slice(0, 6);\n const { start, end } = measureSides(rows);\n if (!start && !end) continue;\n rails.push({\n end,\n fill: false,\n height: tableEl.offsetHeight,\n host,\n start,\n width: tableEl.offsetWidth,\n });\n }\n return rails;\n};\n\nconst sameRails = (a: Rail[], b: Rail[]) =>\n a.length === b.length &&\n a.every(\n (rail, i) =>\n rail.host === b[i].host &&\n rail.start === b[i].start &&\n rail.end === b[i].end &&\n rail.width === b[i].width &&\n rail.height === b[i].height,\n );\n\n/**\n * One frosted backdrop per fixed side instead of one per cell. A per-cell `backdrop-filter`\n * blurs each box on its own, so the column shows seams at every row. Here a rail is portaled\n * into each scroll host (the table's scroll container, a split header / body, or the virtual\n * row layer) and holds two sticky panes spanning the fixed-start / fixed-end width and the\n * full height. The rail sits at z-index 1: above the scrolling cells (z auto), below the\n * fixed cells (z >= 2), so their dividers and content stay sharp on top of the blur.\n */\nconst FixedFrost = memo<{ rootRef: RefObject<HTMLElement | null> }>(({ rootRef }) => {\n const [rails, setRails] = useState<Rail[]>([]);\n\n // Passive effect: the root ref belongs to an ancestor and is attached after this\n // child's layout effects, so a layout effect would see it as null on mount.\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n let frame = 0;\n\n const update = () => {\n frame = 0;\n const table = root.querySelector<HTMLElement>(`${p}`);\n const next = table ? collectRails(table) : [];\n for (const rail of next) {\n if (!rail.fill && getComputedStyle(rail.host).position === 'static') {\n rail.host.style.position = 'relative';\n }\n }\n setRails((prev) => (sameRails(prev, next) ? prev : next));\n };\n const schedule = () => {\n if (!frame) frame = requestAnimationFrame(update);\n };\n\n update();\n // Environments without ResizeObserver (e.g. jsdom in consumer tests) still get\n // the initial measurement and DOM-mutation updates.\n const resize = typeof ResizeObserver === 'undefined' ? undefined : new ResizeObserver(schedule);\n resize?.observe(root);\n const mutation = new MutationObserver((records) => {\n // Ignore our own rail nodes.\n if (records.every((r) => (r.target as Element).closest?.('[data-table-frost]'))) return;\n schedule();\n });\n mutation.observe(root, { attributeFilter: ['class', 'style'], childList: true, subtree: true });\n\n return () => {\n if (frame) cancelAnimationFrame(frame);\n resize?.disconnect();\n mutation.disconnect();\n };\n }, [rootRef]);\n\n return (\n <>\n {rails.map((rail, i) =>\n createPortal(\n <div\n aria-hidden\n className={styles.frostRail}\n data-table-frost=\"\"\n style={rail.fill ? { inset: 0 } : { height: rail.height, width: rail.width }}\n >\n {rail.start > 0 && <div className={styles.frostStart} style={{ width: rail.start }} />}\n {rail.end > 0 && <div className={styles.frostEnd} style={{ width: rail.end }} />}\n </div>,\n rail.host,\n `frost-${i}`,\n ),\n )}\n </>\n );\n});\n\nFixedFrost.displayName = 'TableFixedFrost';\n\nexport default FixedFrost;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FixedFrost.mjs","names":[],"sources":["../../../src/base-ui/Table/FixedFrost.tsx"],"sourcesContent":["'use client';\n\nimport { memo, type RefObject, useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { PREFIX_CLS, styles } from './style';\n\nconst p = `.${PREFIX_CLS}`;\n\ninterface Rail {\n end: number;\n /** Table hosts size the rail to the table; the virtual body fills its row layer. */\n fill: boolean;\n height: number;\n host: HTMLElement;\n start: number;\n width: number;\n}\n\nconst px = (value: string) => Number.parseFloat(value) || 0;\n\n/** Widths of the fixed-start / fixed-end blocks: max sticky offset + cell width over the rows. */\nconst measureSides = (rows: Element[]) => {\n let start = 0;\n let end = 0;\n for (const row of rows) {\n for (const cell of Array.from(row.children) as HTMLElement[]) {\n if (cell.classList.contains(`${PREFIX_CLS}-cell-fix-start`)) {\n start = Math.max(\n start,\n px(cell.style.insetInlineStart || cell.style.left) + cell.offsetWidth,\n );\n } else if (cell.classList.contains(`${PREFIX_CLS}-cell-fix-end`)) {\n end = Math.max(end, px(cell.style.insetInlineEnd || cell.style.right) + cell.offsetWidth);\n }\n }\n }\n return { end: Math.round(end), start: Math.round(start) };\n};\n\nconst collectRails = (table: HTMLElement): Rail[] => {\n const rails: Rail[] = [];\n const own = (el: Element) => el.closest(p) === table;\n const ownMatch = (selector: string) =>\n Array.from(table.querySelectorAll(selector)).some((el) => own(el));\n\n // Empty / skeleton body: the placeholder row spans every column, so there is nothing fixed\n // in the body and nothing scrolled under the fixed side; a rail would only blur the\n // skeleton and its row dividers.\n if (ownMatch(`${p}-placeholder`) || ownMatch('[data-table-skeleton]')) return rails;\n\n // Only frost a side while content is actually scrolled under it. rc-table flags the edge\n // fixed cell with `*-shadow-show` exactly then (scrollLeft > 0 for start, not at the end\n // for end); at rest the transparent fixed cells sit over nothing.\n const showStart = ownMatch(`.${PREFIX_CLS}-cell-fix-start-shadow-show`);\n const showEnd = ownMatch(`.${PREFIX_CLS}-cell-fix-end-shadow-show`);\n if (!showStart && !showEnd) return rails;\n const hosts = table.querySelectorAll<HTMLElement>(\n `${p}-content, ${p}-header, ${p}-body, ${p}-tbody-virtual-holder-inner`,\n );\n\n for (const host of Array.from(hosts)) {\n if (!own(host)) continue;\n // A sticky header is frosted as one element by CSS (it is a backdrop root anyway).\n if (host.closest(`${p}-sticky-holder`)) continue;\n\n if (host.classList.contains(`${PREFIX_CLS}-tbody-virtual-holder-inner`)) {\n const rows = Array.from(host.children).filter(\n (el) =>\n el.classList.contains(`${PREFIX_CLS}-row`) &&\n !el.classList.contains(`${PREFIX_CLS}-row-extra`),\n );\n const measured = measureSides(rows.slice(0, 3));\n const start = showStart ? measured.start : 0;\n const end = showEnd ? measured.end : 0;\n if (start || end) rails.push({ end, fill: true, height: 0, host, start, width: 0 });\n continue;\n }\n\n const tableEl = host.querySelector<HTMLTableElement>(':scope > table');\n if (!tableEl) continue;\n const rows = Array.from(tableEl.querySelectorAll(':scope > thead > tr, :scope > tbody > tr'))\n .filter((row) => !row.classList.contains(`${PREFIX_CLS}-measure-row`))\n .slice(0, 6);\n const measured = measureSides(rows);\n const start = showStart ? measured.start : 0;\n const end = showEnd ? measured.end : 0;\n if (!start && !end) continue;\n rails.push({\n end,\n fill: false,\n height: tableEl.offsetHeight,\n host,\n start,\n width: tableEl.offsetWidth,\n });\n }\n return rails;\n};\n\nconst sameRails = (a: Rail[], b: Rail[]) =>\n a.length === b.length &&\n a.every(\n (rail, i) =>\n rail.host === b[i].host &&\n rail.start === b[i].start &&\n rail.end === b[i].end &&\n rail.width === b[i].width &&\n rail.height === b[i].height,\n );\n\n/**\n * One frosted backdrop per fixed side instead of one per cell. A per-cell `backdrop-filter`\n * blurs each box on its own, so the column shows seams at every row. Here a rail is portaled\n * into each scroll host (the table's scroll container, a split header / body, or the virtual\n * row layer) and holds two sticky panes spanning the fixed-start / fixed-end width and the\n * full height. The rail sits at z-index 1: above the scrolling cells (z auto), below the\n * fixed cells (z >= 2), so their dividers and content stay sharp on top of the blur.\n * A side is only frosted while content is scrolled under it, never for an empty / skeleton\n * body (empty / loading skeleton), so row dividers stay continuous through fixed columns.\n * With rows and `loading` the rail stays (below the fixed cells and their dividers) so the\n * scrolled content does not show through the see-through fixed cells under the mask.\n */\nconst FixedFrost = memo<{ rootRef: RefObject<HTMLElement | null> }>(({ rootRef }) => {\n const [rails, setRails] = useState<Rail[]>([]);\n\n // Passive effect: the root ref belongs to an ancestor and is attached after this\n // child's layout effects, so a layout effect would see it as null on mount.\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return;\n let frame = 0;\n\n const update = () => {\n frame = 0;\n const table = root.querySelector<HTMLElement>(`${p}`);\n const next = table ? collectRails(table) : [];\n for (const rail of next) {\n if (!rail.fill && getComputedStyle(rail.host).position === 'static') {\n rail.host.style.position = 'relative';\n }\n }\n setRails((prev) => (sameRails(prev, next) ? prev : next));\n };\n const schedule = () => {\n if (!frame) frame = requestAnimationFrame(update);\n };\n\n update();\n // Environments without ResizeObserver (e.g. jsdom in consumer tests) still get\n // the initial measurement and DOM-mutation updates.\n const resize = typeof ResizeObserver === 'undefined' ? undefined : new ResizeObserver(schedule);\n resize?.observe(root);\n const mutation = new MutationObserver((records) => {\n // Ignore our own rail nodes.\n if (records.every((r) => (r.target as Element).closest?.('[data-table-frost]'))) return;\n schedule();\n });\n mutation.observe(root, { attributeFilter: ['class', 'style'], childList: true, subtree: true });\n\n return () => {\n if (frame) cancelAnimationFrame(frame);\n resize?.disconnect();\n mutation.disconnect();\n };\n }, [rootRef]);\n\n return (\n <>\n {rails.map((rail, i) =>\n createPortal(\n <div\n aria-hidden\n className={styles.frostRail}\n data-table-frost=\"\"\n style={rail.fill ? { inset: 0 } : { height: rail.height, width: rail.width }}\n >\n {rail.start > 0 && <div className={styles.frostStart} style={{ width: rail.start }} />}\n {rail.end > 0 && <div className={styles.frostEnd} style={{ width: rail.end }} />}\n </div>,\n rail.host,\n `frost-${i}`,\n ),\n )}\n </>\n );\n});\n\nFixedFrost.displayName = 'TableFixedFrost';\n\nexport default FixedFrost;\n"],"mappings":";;;;;;AAOA,MAAM,IAAI,IAAI;AAYd,MAAM,MAAM,UAAkB,OAAO,WAAW,KAAK,KAAK;;AAG1D,MAAM,gBAAgB,SAAoB;CACxC,IAAI,QAAQ;CACZ,IAAI,MAAM;CACV,KAAK,MAAM,OAAO,MAChB,KAAK,MAAM,QAAQ,MAAM,KAAK,IAAI,QAAQ,GACxC,IAAI,KAAK,UAAU,SAAS,2BAA8B,GACxD,QAAQ,KAAK,IACX,OACA,GAAG,KAAK,MAAM,oBAAoB,KAAK,MAAM,IAAI,IAAI,KAAK,WAC5D;MACK,IAAI,KAAK,UAAU,SAAS,yBAA4B,GAC7D,MAAM,KAAK,IAAI,KAAK,GAAG,KAAK,MAAM,kBAAkB,KAAK,MAAM,KAAK,IAAI,KAAK,WAAW;CAI9F,OAAO;EAAE,KAAK,KAAK,MAAM,GAAG;EAAG,OAAO,KAAK,MAAM,KAAK;CAAE;AAC1D;AAEA,MAAM,gBAAgB,UAA+B;CACnD,MAAM,QAAgB,CAAC;CACvB,MAAM,OAAO,OAAgB,GAAG,QAAQ,CAAC,MAAM;CAC/C,MAAM,YAAY,aAChB,MAAM,KAAK,MAAM,iBAAiB,QAAQ,CAAC,CAAC,CAAC,MAAM,OAAO,IAAI,EAAE,CAAC;CAKnE,IAAI,SAAS,GAAG,EAAE,aAAa,KAAK,SAAS,uBAAuB,GAAG,OAAO;CAK9E,MAAM,YAAY,SAAS,IAAI,WAAW,4BAA4B;CACtE,MAAM,UAAU,SAAS,IAAI,WAAW,0BAA0B;CAClE,IAAI,CAAC,aAAa,CAAC,SAAS,OAAO;CACnC,MAAM,QAAQ,MAAM,iBAClB,GAAG,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,4BAC7C;CAEA,KAAK,MAAM,QAAQ,MAAM,KAAK,KAAK,GAAG;EACpC,IAAI,CAAC,IAAI,IAAI,GAAG;EAEhB,IAAI,KAAK,QAAQ,GAAG,EAAE,eAAe,GAAG;EAExC,IAAI,KAAK,UAAU,SAAS,uCAA0C,GAAG;GACvE,MAAM,OAAO,MAAM,KAAK,KAAK,QAAQ,CAAC,CAAC,QACpC,OACC,GAAG,UAAU,SAAS,gBAAmB,KACzC,CAAC,GAAG,UAAU,SAAS,sBAAyB,CACpD;GACA,MAAM,WAAW,aAAa,KAAK,MAAM,GAAG,CAAC,CAAC;GAC9C,MAAM,QAAQ,YAAY,SAAS,QAAQ;GAC3C,MAAM,MAAM,UAAU,SAAS,MAAM;GACrC,IAAI,SAAS,KAAK,MAAM,KAAK;IAAE;IAAK,MAAM;IAAM,QAAQ;IAAG;IAAM;IAAO,OAAO;GAAE,CAAC;GAClF;EACF;EAEA,MAAM,UAAU,KAAK,cAAgC,gBAAgB;EACrE,IAAI,CAAC,SAAS;EACd,MAAM,OAAO,MAAM,KAAK,QAAQ,iBAAiB,0CAA0C,CAAC,CAAC,CAC1F,QAAQ,QAAQ,CAAC,IAAI,UAAU,SAAS,GAAG,WAAW,aAAa,CAAC,CAAC,CACrE,MAAM,GAAG,CAAC;EACb,MAAM,WAAW,aAAa,IAAI;EAClC,MAAM,QAAQ,YAAY,SAAS,QAAQ;EAC3C,MAAM,MAAM,UAAU,SAAS,MAAM;EACrC,IAAI,CAAC,SAAS,CAAC,KAAK;EACpB,MAAM,KAAK;GACT;GACA,MAAM;GACN,QAAQ,QAAQ;GAChB;GACA;GACA,OAAO,QAAQ;EACjB,CAAC;CACH;CACA,OAAO;AACT;AAEA,MAAM,aAAa,GAAW,MAC5B,EAAE,WAAW,EAAE,UACf,EAAE,OACC,MAAM,MACL,KAAK,SAAS,EAAE,EAAE,CAAC,QACnB,KAAK,UAAU,EAAE,EAAE,CAAC,SACpB,KAAK,QAAQ,EAAE,EAAE,CAAC,OAClB,KAAK,UAAU,EAAE,EAAE,CAAC,SACpB,KAAK,WAAW,EAAE,EAAE,CAAC,MACzB;;;;;;;;;;;;;AAcF,MAAM,aAAa,MAAkD,EAAE,cAAc;CACnF,MAAM,CAAC,OAAO,YAAY,SAAiB,CAAC,CAAC;CAI7C,gBAAgB;EACd,MAAM,OAAO,QAAQ;EACrB,IAAI,CAAC,MAAM;EACX,IAAI,QAAQ;EAEZ,MAAM,eAAe;GACnB,QAAQ;GACR,MAAM,QAAQ,KAAK,cAA2B,GAAG,GAAG;GACpD,MAAM,OAAO,QAAQ,aAAa,KAAK,IAAI,CAAC;GAC5C,KAAK,MAAM,QAAQ,MACjB,IAAI,CAAC,KAAK,QAAQ,iBAAiB,KAAK,IAAI,CAAC,CAAC,aAAa,UACzD,KAAK,KAAK,MAAM,WAAW;GAG/B,UAAU,SAAU,UAAU,MAAM,IAAI,IAAI,OAAO,IAAK;EAC1D;EACA,MAAM,iBAAiB;GACrB,IAAI,CAAC,OAAO,QAAQ,sBAAsB,MAAM;EAClD;EAEA,OAAO;EAGP,MAAM,SAAS,OAAO,mBAAmB,cAAc,KAAA,IAAY,IAAI,eAAe,QAAQ;EAC9F,QAAQ,QAAQ,IAAI;EACpB,MAAM,WAAW,IAAI,kBAAkB,YAAY;GAEjD,IAAI,QAAQ,OAAO,MAAO,EAAE,OAAmB,UAAU,oBAAoB,CAAC,GAAG;GACjF,SAAS;EACX,CAAC;EACD,SAAS,QAAQ,MAAM;GAAE,iBAAiB,CAAC,SAAS,OAAO;GAAG,WAAW;GAAM,SAAS;EAAK,CAAC;EAE9F,aAAa;GACX,IAAI,OAAO,qBAAqB,KAAK;GACrC,QAAQ,WAAW;GACnB,SAAS,WAAW;EACtB;CACF,GAAG,CAAC,OAAO,CAAC;CAEZ,OACE,oBAAA,YAAA,EAAA,UACG,MAAM,KAAK,MAAM,MAChB,aACE,qBAAC,OAAD;EACE,eAAA;EACA,WAAW,OAAO;EAClB,oBAAiB;EACjB,OAAO,KAAK,OAAO,EAAE,OAAO,EAAE,IAAI;GAAE,QAAQ,KAAK;GAAQ,OAAO,KAAK;EAAM;EAJ7E,UAAA,CAMG,KAAK,QAAQ,KAAK,oBAAC,OAAD;GAAK,WAAW,OAAO;GAAY,OAAO,EAAE,OAAO,KAAK,MAAM;EAAI,CAAA,GACpF,KAAK,MAAM,KAAK,oBAAC,OAAD;GAAK,WAAW,OAAO;GAAU,OAAO,EAAE,OAAO,KAAK,IAAI;EAAI,CAAA,CAC5E;CACL,CAAA,GAAA,KAAK,MACL,SAAS,GACX,CACF,EACA,CAAA;AAEN,CAAC;AAED,WAAW,cAAc"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import Block from "../../Block/Block.mjs";
|
|
2
3
|
import { Tooltip } from "../Tooltip/Tooltip.mjs";
|
|
3
4
|
import ActionIcon from "../ActionIcon/ActionIcon.mjs";
|
|
4
5
|
import { useTranslation } from "../../i18n/useTranslation.mjs";
|
|
@@ -417,14 +418,16 @@ const TableInner = (props) => {
|
|
|
417
418
|
icon: Inbox,
|
|
418
419
|
imageSize: 40
|
|
419
420
|
}) : typeof customEmpty === "function" ? customEmpty() : customEmpty;
|
|
421
|
+
const columnsCount = flattenColumns(columns).length + 2;
|
|
420
422
|
const TableComponent = virtual ? VirtualTable : RcTable;
|
|
421
423
|
return /* @__PURE__ */ jsxs("div", {
|
|
422
424
|
ref: rootRef,
|
|
425
|
+
className: cx(styles.root, `${PREFIX_CLS}-wrapper`, rootClassName, className, mergedClassNames.root),
|
|
423
426
|
style: {
|
|
427
|
+
"--columns-count": columnsCount,
|
|
424
428
|
...mergedStyles.root,
|
|
425
429
|
...style
|
|
426
430
|
},
|
|
427
|
-
className: cx(styles.root, `${PREFIX_CLS}-wrapper`, rootClassName, className, mergedClassNames.root),
|
|
428
431
|
children: [
|
|
429
432
|
topPagination,
|
|
430
433
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -475,10 +478,17 @@ const TableInner = (props) => {
|
|
|
475
478
|
onScroll
|
|
476
479
|
}),
|
|
477
480
|
/* @__PURE__ */ jsx(FixedFrost, { rootRef }),
|
|
478
|
-
isLoading && /* @__PURE__ */
|
|
481
|
+
isLoading && /* @__PURE__ */ jsx("div", {
|
|
479
482
|
className: styles.loading,
|
|
480
483
|
"data-table-loading": "",
|
|
481
|
-
children:
|
|
484
|
+
children: /* @__PURE__ */ jsxs(Block, {
|
|
485
|
+
align: "center",
|
|
486
|
+
"data-table-loading-indicator": "",
|
|
487
|
+
gap: 8,
|
|
488
|
+
padding: 12,
|
|
489
|
+
variant: "outlined",
|
|
490
|
+
children: [/* @__PURE__ */ jsx(Spin, { ...spinProps }), tip]
|
|
491
|
+
})
|
|
482
492
|
})
|
|
483
493
|
]
|
|
484
494
|
}),
|