plass-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.
Files changed (165) hide show
  1. package/README.md +165 -0
  2. package/dist/components/accordion/PlAccordion.js +1 -131
  3. package/dist/components/accordion/index.js +1 -1
  4. package/dist/components/alert/PlAlert.js +1 -109
  5. package/dist/components/alert/index.js +1 -1
  6. package/dist/components/animate-appear/PlAnimateAppear.js +1 -71
  7. package/dist/components/animate-appear/index.js +1 -1
  8. package/dist/components/animate-blink/PlAnimateBlink.js +1 -47
  9. package/dist/components/animate-blink/index.js +1 -1
  10. package/dist/components/animate-fade/PlAnimateFade.js +1 -48
  11. package/dist/components/animate-fade/index.js +1 -1
  12. package/dist/components/animate-grow/PlAnimateGrow.js +1 -49
  13. package/dist/components/animate-grow/index.js +1 -1
  14. package/dist/components/animate-headline/PlAnimateHeadline.js +1 -120
  15. package/dist/components/animate-headline/index.js +1 -1
  16. package/dist/components/animate-lighting/PlAnimateLighting.js +1 -65
  17. package/dist/components/animate-lighting/index.js +1 -1
  18. package/dist/components/animate-marquee/PlAnimateMarquee.js +1 -94
  19. package/dist/components/animate-marquee/index.js +1 -1
  20. package/dist/components/animate-rotate/PlAnimateRotate.js +1 -50
  21. package/dist/components/animate-rotate/index.js +1 -1
  22. package/dist/components/animate-slide/PlAnimateSlide.js +1 -49
  23. package/dist/components/animate-slide/index.js +1 -1
  24. package/dist/components/animate-typing/PlAnimateTyping.js +1 -177
  25. package/dist/components/animate-typing/index.js +1 -1
  26. package/dist/components/animate-zoom/PlAnimateZoom.js +1 -45
  27. package/dist/components/animate-zoom/index.js +1 -1
  28. package/dist/components/aspect-ratio/PlAspectRatio.js +1 -58
  29. package/dist/components/aspect-ratio/index.js +1 -1
  30. package/dist/components/avatar/PlAvatar.js +1 -121
  31. package/dist/components/avatar/index.js +1 -1
  32. package/dist/components/badge/PlBadge.js +1 -168
  33. package/dist/components/badge/index.js +1 -1
  34. package/dist/components/blockquote/PlBlockquote.js +1 -112
  35. package/dist/components/blockquote/index.js +1 -1
  36. package/dist/components/bottom-navigation/PlBottomNavigation.js +1 -141
  37. package/dist/components/bottom-navigation/index.js +1 -1
  38. package/dist/components/box/PlBox.js +1 -46
  39. package/dist/components/box/index.js +1 -1
  40. package/dist/components/breadcrumb/PlBreadcrumb.js +1 -201
  41. package/dist/components/breadcrumb/index.js +1 -1
  42. package/dist/components/button/PlButton.js +1 -196
  43. package/dist/components/button/index.js +1 -1
  44. package/dist/components/button-group/PlButtonGroup.js +1 -64
  45. package/dist/components/button-group/index.js +1 -1
  46. package/dist/components/card/PlCard.js +1 -102
  47. package/dist/components/card/index.js +1 -1
  48. package/dist/components/carousel/PlCarousel.js +1 -177
  49. package/dist/components/carousel/index.js +1 -1
  50. package/dist/components/chat-bubble/PlChatBubble.js +1 -206
  51. package/dist/components/chat-bubble/index.js +1 -1
  52. package/dist/components/checkbox/PlCheckbox.js +1 -100
  53. package/dist/components/checkbox/index.js +1 -1
  54. package/dist/components/chip/PlChip.js +1 -144
  55. package/dist/components/chip/index.js +1 -1
  56. package/dist/components/collapsible/PlCollapsible.js +1 -65
  57. package/dist/components/collapsible/index.js +1 -1
  58. package/dist/components/combobox/PlCombobox.js +1 -199
  59. package/dist/components/combobox/index.js +1 -1
  60. package/dist/components/container/PlContainer.js +1 -47
  61. package/dist/components/container/index.js +1 -1
  62. package/dist/components/date-picker/PlDatePicker.js +1 -87
  63. package/dist/components/date-picker/index.js +1 -1
  64. package/dist/components/date-range-picker/PlDateRangePicker.js +1 -152
  65. package/dist/components/date-range-picker/index.js +1 -1
  66. package/dist/components/date-time-picker/PlDateTimePicker.js +1 -106
  67. package/dist/components/date-time-picker/index.js +1 -1
  68. package/dist/components/divider/PlDivider.js +1 -107
  69. package/dist/components/divider/index.js +1 -1
  70. package/dist/components/drawer/PlDrawer.js +1 -190
  71. package/dist/components/drawer/index.js +1 -1
  72. package/dist/components/file-picker/PlFilePicker.js +1 -274
  73. package/dist/components/file-picker/index.js +1 -1
  74. package/dist/components/floating-bottom-navigation/PlFloatingBottomNavigation.js +1 -291
  75. package/dist/components/floating-bottom-navigation/index.js +1 -1
  76. package/dist/components/grid/PlGrid.js +1 -51
  77. package/dist/components/grid/PlGridItem.js +1 -34
  78. package/dist/components/grid/index.js +1 -2
  79. package/dist/components/highlight/PlHighlight.js +1 -185
  80. package/dist/components/highlight/index.js +1 -1
  81. package/dist/components/hot-keys/PlHotKeys.js +1 -294
  82. package/dist/components/hot-keys/index.js +1 -1
  83. package/dist/components/icon/PlIcon.js +1 -58
  84. package/dist/components/icon/index.js +1 -1
  85. package/dist/components/icon-button/PlIconButton.js +1 -37
  86. package/dist/components/icon-button/index.js +1 -1
  87. package/dist/components/list/PlList.js +1 -160
  88. package/dist/components/list/index.js +1 -1
  89. package/dist/components/menu/PlMenu.js +1 -209
  90. package/dist/components/menu/index.js +1 -1
  91. package/dist/components/modal/PlModal.js +1 -150
  92. package/dist/components/modal/index.js +1 -1
  93. package/dist/components/number-field/PlNumberField.js +1 -111
  94. package/dist/components/number-field/index.js +1 -1
  95. package/dist/components/otp-field/PlOtpField.js +1 -109
  96. package/dist/components/otp-field/index.js +1 -1
  97. package/dist/components/overlay/PlOverlay.js +1 -77
  98. package/dist/components/overlay/index.js +1 -1
  99. package/dist/components/pagination/PlPagination.js +1 -159
  100. package/dist/components/pagination/index.js +1 -1
  101. package/dist/components/panes/PlPanes.js +1 -324
  102. package/dist/components/panes/index.js +1 -1
  103. package/dist/components/pill/PlPill.js +1 -154
  104. package/dist/components/pill/index.js +1 -1
  105. package/dist/components/popover/PlPopover.js +1 -113
  106. package/dist/components/popover/index.js +1 -1
  107. package/dist/components/progress-box/PlProgressBox.js +1 -34
  108. package/dist/components/progress-box/index.js +1 -1
  109. package/dist/components/progress-circular/PlProgressCircular.js +1 -47
  110. package/dist/components/progress-circular/index.js +1 -1
  111. package/dist/components/progress-linear/PlProgressLinear.js +1 -40
  112. package/dist/components/progress-linear/index.js +1 -1
  113. package/dist/components/radio-group/PlRadioGroup.js +1 -99
  114. package/dist/components/radio-group/index.js +1 -1
  115. package/dist/components/rating/PlRating.js +1 -101
  116. package/dist/components/rating/index.js +1 -1
  117. package/dist/components/scroll-zone/PlScrollZone.js +1 -411
  118. package/dist/components/scroll-zone/index.js +1 -1
  119. package/dist/components/segmented-button/PlSegmentedButton.js +1 -206
  120. package/dist/components/segmented-button/index.js +1 -1
  121. package/dist/components/select/PlSelect.js +1 -115
  122. package/dist/components/select/index.js +1 -1
  123. package/dist/components/skeleton/PlSkeleton.js +1 -142
  124. package/dist/components/skeleton/index.js +1 -1
  125. package/dist/components/slider/PlSlider.js +1 -132
  126. package/dist/components/slider/index.js +1 -1
  127. package/dist/components/spoiler/PlSpoiler.js +1 -74
  128. package/dist/components/spoiler/index.js +1 -1
  129. package/dist/components/switch/PlSwitch.js +1 -131
  130. package/dist/components/switch/index.js +1 -1
  131. package/dist/components/table/PlTable.js +1 -210
  132. package/dist/components/table/index.js +1 -1
  133. package/dist/components/tabs/PlTabs.js +1 -182
  134. package/dist/components/tabs/index.js +1 -1
  135. package/dist/components/text-field/PlTextField.js +1 -126
  136. package/dist/components/text-field/index.js +1 -1
  137. package/dist/components/text-link/PlTextLink.js +1 -136
  138. package/dist/components/text-link/index.js +1 -1
  139. package/dist/components/time-picker/PlTimePicker.js +1 -97
  140. package/dist/components/time-picker/index.js +1 -1
  141. package/dist/components/timeline/PlTimeline.js +1 -207
  142. package/dist/components/timeline/index.js +1 -1
  143. package/dist/components/toast/PlToast.js +1 -174
  144. package/dist/components/toast/index.js +1 -1
  145. package/dist/components/toolbar/PlToolbar.js +1 -65
  146. package/dist/components/toolbar/index.js +1 -1
  147. package/dist/components/tooltip/PlTooltip.js +1 -117
  148. package/dist/components/tooltip/index.js +1 -1
  149. package/dist/components/typography/PlTypography.js +1 -143
  150. package/dist/components/typography/index.js +1 -1
  151. package/dist/index.js +1 -75
  152. package/dist/internal/animate.js +1 -318
  153. package/dist/internal/button-group.js +2 -19
  154. package/dist/internal/calendar.js +1 -501
  155. package/dist/internal/date.js +1 -353
  156. package/dist/internal/format.js +1 -41
  157. package/dist/internal/grid.js +1 -143
  158. package/dist/internal/icons.js +1 -138
  159. package/dist/internal/menu.js +1 -18
  160. package/dist/internal/picker.js +1 -139
  161. package/dist/internal/progress.js +1 -167
  162. package/dist/internal/sizer.js +1 -35
  163. package/dist/internal/styles.js +1 -636
  164. package/dist/types.js +0 -8
  165. package/package.json +5 -3
@@ -1,109 +1 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import * as React from 'react';
3
- import { Field } from '@base-ui/react/field';
4
- import { OTPField } from '@base-ui/react/otp-field';
5
- import { cx, disabledClasses, fieldReadOnlyClasses, fieldRestClasses, hasContent, metaTextClasses, stackGapClasses, surfaceSlots, transitionClasses } from '../../internal/styles.js';
6
- /** How many slots a code may have. Two is the shortest thing worth splitting. */
7
- const MIN_LENGTH = 2;
8
- const MAX_LENGTH = 12;
9
- /**
10
- * A slot's box.
11
- *
12
- * Its own ladder rather than `controlHeightClasses`, for the reason a tick box
13
- * has one: a slot is not a control in a row of controls, it is a character
14
- * standing on its own, and an `md` slot the height of an `md` `PlButton` would
15
- * be too small to read a code out of across a desk. Every step is taller than it
16
- * is wide, which is what makes a row of them read as places for one character
17
- * each rather than as a row of tiny fields.
18
- */
19
- const slotSizeClasses = {
20
- xs: 'h-7 w-6',
21
- sm: 'h-8 w-7',
22
- md: 'h-10 w-8',
23
- lg: 'h-12 w-10',
24
- xl: 'h-14 w-12'
25
- };
26
- /**
27
- * And its own radius, for the reason a tick box has one.
28
- *
29
- * `radiusClasses` is a percentage of a *control's height*, which is a cut corner
30
- * on something wide and a lozenge on something nearly square: `md` is 12px, and
31
- * a 12px corner on a 32px-wide box is most of the way to a pill. These are
32
- * ~22% of the slot's width instead, which is the same amount of cut on this
33
- * shape — a sheet with the corners taken off, never a pill.
34
- */
35
- const slotRadiusClasses = {
36
- xs: 'rounded-[0.3125rem]',
37
- sm: 'rounded-[0.375rem]',
38
- md: 'rounded-[0.4375rem]',
39
- lg: 'rounded-[0.5625rem]',
40
- xl: 'rounded-[0.6875rem]'
41
- };
42
- /**
43
- * And its own type scale, two steps up the control ladder. A verification code
44
- * is read out loud off a phone and typed with the other hand; it is the one
45
- * piece of text in a form that should be bigger than the label above it.
46
- */
47
- const slotTextClasses = {
48
- xs: 'text-[0.8125rem]',
49
- sm: 'text-[0.9375rem]',
50
- md: 'text-[1.0625rem]',
51
- lg: 'text-[1.25rem]',
52
- xl: 'text-[1.5rem]'
53
- };
54
- /**
55
- * Between the slots, and the only thing `density` touches here — spacing, never
56
- * the box and never the type scale, exactly as everywhere else in the library.
57
- */
58
- const slotGapClasses = {
59
- default: { xs: 'gap-1', sm: 'gap-1', md: 'gap-1.5', lg: 'gap-2', xl: 'gap-2.5' },
60
- compact: { xs: 'gap-0.5', sm: 'gap-0.5', md: 'gap-1', lg: 'gap-1', xl: 'gap-1.5' }
61
- };
62
- /** `charset` is the library's word; Base UI's is `validationType`. */
63
- const validationTypes = {
64
- numeric: 'numeric',
65
- alpha: 'alpha',
66
- alphanumeric: 'alphanumeric',
67
- any: 'none'
68
- };
69
- /**
70
- * A row of one-character slots: a PIN, a texted verification code, an invite
71
- * key.
72
- *
73
- * Base UI owns everything that makes this harder than it looks — one hidden
74
- * value behind however many inputs, paste spread across the slots from wherever
75
- * the caret was, backspace stepping back a box, a click landing on the first
76
- * empty slot rather than the one under the pointer, and the autofill hook that
77
- * lets a phone offer the code straight from the message.
78
- *
79
- * What is here is the ladder a slot is drawn on and the field shell it shares
80
- * with `PlTextField` and `PlSelect` — a slot is a field-shaped box, and a form
81
- * holding both should not look like two form kits stacked on each other.
82
- */
83
- export const PlOtpField = /* @__PURE__ */ React.forwardRef(function PlOtpField({ variant = 'glass', size = 'md', color = 'primary', density = 'default', elevation = 0, length = 6, charset = 'numeric', mask = false, groupSize, separator = '–', value, defaultValue, onValueChange, onComplete, onValueInvalid, autoSubmit = false, label, description, error, invalid, name, required = false, disabled = false, readOnly = false, autoFocus = false, className, style, ...props }, ref) {
84
- const slots = Math.min(MAX_LENGTH, Math.max(MIN_LENGTH, Math.round(length)));
85
- const hasError = hasContent(error);
86
- const isInvalid = invalid ?? hasError;
87
- // Invalid re-points the whole slot family at `danger`, exactly as on
88
- // PlTextField, so the edge, the ring, the caret and the message all turn over
89
- // together and no state needs tokens of its own.
90
- const family = isInvalid ? 'danger' : color;
91
- const slotClassNames = cx(
92
- // `font-family` rather than the `font` shorthand: the shorthand would take
93
- // the inherited font *size* with it and undo the ladder set on the next
94
- // line.
95
- 'text-center font-medium [font-family:inherit]', slotSizeClasses[size], slotTextClasses[size], slotRadiusClasses[size], transitionClasses, 'caret-(--p-accent) selection:bg-(--p-soft-press)',
96
- // `focus` rather than `focus-visible`: a slot is put in focus by clicking it
97
- // as often as by typing into it, and the ring is the only thing saying which
98
- // character the next keystroke lands on.
99
- 'focus:[outline:2px_solid_var(--p-ring)] focus:[outline-offset:0px]', 'focus:[transition-duration:0ms]',
100
- // An if/else rather than stacked variants: two Tailwind classes of equal
101
- // specificity resolve by their order in the generated stylesheet.
102
- disabled
103
- ? disabledClasses[variant]
104
- : readOnly
105
- ? fieldReadOnlyClasses[variant]
106
- : fieldRestClasses[variant]);
107
- const separatorEvery = groupSize && groupSize > 0 ? Math.round(groupSize) : 0;
108
- return (_jsxs(Field.Root, { disabled: disabled, invalid: isInvalid, className: cx('inline-flex flex-col align-top', stackGapClasses[size], className), style: { ...surfaceSlots(family, elevation), ...style }, children: [hasContent(label) ? (_jsx(Field.Label, { className: cx(metaTextClasses[size], 'font-medium', disabled ? 'text-(--plass-muted-fg)' : 'text-(--plass-fg)'), children: label })) : null, _jsx(OTPField.Root, { ref: ref, length: slots, validationType: validationTypes[charset], mask: mask, name: name, required: required, disabled: disabled, readOnly: readOnly, autoSubmit: autoSubmit, value: value, defaultValue: defaultValue, onValueChange: (next) => onValueChange?.(next), onValueComplete: (next) => onComplete?.(next), onValueInvalid: (next) => onValueInvalid?.(next), className: cx('flex items-center', slotGapClasses[density][size]), ...props, children: Array.from({ length: slots }, (_, index) => (_jsxs(React.Fragment, { children: [separatorEvery > 0 && index > 0 && index % separatorEvery === 0 ? (_jsx("span", { "aria-hidden": "true", className: cx('select-none px-0.5 text-(--plass-muted-fg)', slotTextClasses[size]), children: separator })) : null, _jsx(OTPField.Input, { className: slotClassNames, autoFocus: autoFocus && index === 0 })] }, index))) }), hasContent(description) ? (_jsx(Field.Description, { className: cx(metaTextClasses[size], 'text-(--plass-muted-fg)'), children: description })) : null, hasError ? (_jsx(Field.Error, { match: true, className: cx(metaTextClasses[size], 'text-(--p-accent)'), children: error })) : null] }));
109
- });
1
+ "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{Field as l}from"@base-ui/react/field";import{OTPField as r}from"@base-ui/react/otp-field";import{cx as n,disabledClasses as s,fieldReadOnlyClasses as i,fieldRestClasses as o,hasContent as m,metaTextClasses as d,stackGapClasses as u,surfaceSlots as c,transitionClasses as p}from"../../internal/styles.js";const f={xs:"h-7 w-6",sm:"h-8 w-7",md:"h-10 w-8",lg:"h-12 w-10",xl:"h-14 w-12"},x={xs:"rounded-[0.3125rem]",sm:"rounded-[0.375rem]",md:"rounded-[0.4375rem]",lg:"rounded-[0.5625rem]",xl:"rounded-[0.6875rem]"},g={xs:"text-[0.8125rem]",sm:"text-[0.9375rem]",md:"text-[1.0625rem]",lg:"text-[1.25rem]",xl:"text-[1.5rem]"},h={default:{xs:"gap-1",sm:"gap-1",md:"gap-1.5",lg:"gap-2",xl:"gap-2.5"},compact:{xs:"gap-0.5",sm:"gap-0.5",md:"gap-1",lg:"gap-1",xl:"gap-1.5"}},y={numeric:"numeric",alpha:"alpha",alphanumeric:"alphanumeric",any:"none"};export const PlOtpField=/* @__PURE__ */t.forwardRef(function PlOtpField({variant:b="glass",size:v="md",color:N="primary",density:V="default",elevation:w=0,length:F=6,charset:j="numeric",mask:C=!1,groupSize:M,separator:O="–",value:I,defaultValue:R,onValueChange:S,onComplete:k,onValueInvalid:q,autoSubmit:z=!1,label:P,description:_,error:A,invalid:D,name:E,required:L=!1,disabled:T=!1,readOnly:B=!1,autoFocus:G=!1,className:H,style:J,...K},Q){const U=Math.min(12,Math.max(2,Math.round(F))),W=m(A),X=D??W,Y=X?"danger":N,Z=n("text-center font-medium [font-family:inherit]",f[v],g[v],x[v],p,"caret-(--p-accent) selection:bg-(--p-soft-press)","focus:[outline:2px_solid_var(--p-ring)] focus:[outline-offset:0px]","focus:[transition-duration:0ms]",T?s[b]:B?i[b]:o[b]),$=M&&M>0?Math.round(M):0;return a(l.Root,{disabled:T,invalid:X,className:n("inline-flex flex-col align-top",u[v],H),style:{...c(Y,w),...J},children:[m(P)?e(l.Label,{className:n(d[v],"font-medium",T?"text-(--plass-muted-fg)":"text-(--plass-fg)"),children:P}):null,e(r.Root,{ref:Q,length:U,validationType:y[j],mask:C,name:E,required:L,disabled:T,readOnly:B,autoSubmit:z,value:I,defaultValue:R,onValueChange:e=>S?.(e),onValueComplete:e=>k?.(e),onValueInvalid:e=>q?.(e),className:n("flex items-center",h[V][v]),...K,children:Array.from({length:U},(l,s)=>a(t.Fragment,{children:[$>0&&s>0&&s%$===0?e("span",{"aria-hidden":"true",className:n("select-none px-0.5 text-(--plass-muted-fg)",g[v]),children:O}):null,e(r.Input,{className:Z,autoFocus:G&&0===s})]},s))}),m(_)?e(l.Description,{className:n(d[v],"text-(--plass-muted-fg)"),children:_}):null,W?e(l.Error,{match:!0,className:n(d[v],"text-(--p-accent)"),children:A}):null]})});
@@ -1 +1 @@
1
- export { PlOtpField } from './PlOtpField.js';
1
+ export{PlOtpField}from"./PlOtpField.js";
@@ -1,77 +1 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Dialog as BaseUIDialog } from '@base-ui/react/dialog';
3
- import { surfaceSlots } from '../../internal/styles.js';
4
- /**
5
- * The four tones.
6
- *
7
- * `scrim` matches `PlModal`'s backdrop exactly — the two have to, or a modal
8
- * opened over an overlay would show a seam. `clear` draws nothing and still
9
- * covers the viewport, so it goes on catching pointer events.
10
- */
11
- const toneClasses = {
12
- scrim: 'bg-(--plass-scrim) [backdrop-filter:blur(2px)] [-webkit-backdrop-filter:blur(2px)]',
13
- glass: /* @__PURE__ */ [
14
- '[background-color:color-mix(in_oklab,var(--plass-scrim)_45%,transparent)]',
15
- '[backdrop-filter:var(--plass-blur)] [-webkit-backdrop-filter:var(--plass-blur)]'
16
- ].join(' '),
17
- solid: 'bg-(--plass-surface)',
18
- clear: ''
19
- };
20
- const alignClasses = {
21
- start: 'items-start',
22
- center: 'items-center',
23
- end: 'items-end'
24
- };
25
- /** The padding between the content and the edge of the viewport. */
26
- const insetClasses = {
27
- xs: 'p-3',
28
- sm: 'p-4',
29
- md: 'p-6',
30
- lg: 'p-8',
31
- xl: 'p-10'
32
- };
33
- /**
34
- * Opacity only, on both the scrim and the content. An overlay that scales or
35
- * slides drags whatever is written on it across the screen, which is the one
36
- * thing the house style is against — and unlike a control, this one is usually
37
- * carrying a sentence.
38
- */
39
- const fadeClasses = /* @__PURE__ */ [
40
- '[transition:opacity_var(--plass-duration)_var(--plass-ease)]',
41
- 'data-[starting-style]:opacity-0 data-[ending-style]:opacity-0'
42
- ].join(' ');
43
- /**
44
- * A sheet over the whole page that stops it being used.
45
- *
46
- * The difference from a `PlModal` is what is *not* here: no surface, no border,
47
- * no title, no actions. An overlay is the scrim on its own, with whatever the
48
- * caller puts on top of it — most often a spinner and a line saying what is
49
- * being waited for.
50
- *
51
- * It is not dismissible by default, and that is the one prop worth reading
52
- * twice. Everything else Base UI owns: the portal, the scroll lock, the focus
53
- * held inside, the page behind going inert, and focus returning to wherever it
54
- * came from when the overlay closes.
55
- */
56
- export function PlOverlay({ open, defaultOpen, onOpenChange, tone = 'scrim', dismissible = false, modal = true, align = 'center', size = 'md', color = 'primary', label = 'Overlay', className, style, children, ...props }) {
57
- return (_jsx(BaseUIDialog.Root, { open: open, defaultOpen: defaultOpen, modal: modal, disablePointerDismissal: !dismissible, onOpenChange: (next, details) => {
58
- // `disablePointerDismissal` covers the click; Escape has no prop of its
59
- // own, so it is cancelled here by the reason the change arrives with.
60
- if (!dismissible && !next && details.reason === 'escape-key') {
61
- details.cancel();
62
- return;
63
- }
64
- onOpenChange?.(next);
65
- }, children: _jsxs(BaseUIDialog.Portal, { children: [_jsx(BaseUIDialog.Backdrop, { className: `plass-portal fixed inset-0 z-50 ${fadeClasses} ${toneClasses[tone]}` }), _jsx(BaseUIDialog.Viewport, { className: [
66
- 'plass-portal fixed inset-0 z-50 flex justify-center',
67
- alignClasses[align],
68
- insetClasses[size]
69
- ].join(' '), children: _jsx(BaseUIDialog.Popup, { "aria-label": label, className: [
70
- 'flex max-h-full max-w-full flex-col items-center justify-center',
71
- '[outline:none]',
72
- fadeClasses,
73
- className ?? ''
74
- ]
75
- .filter(Boolean)
76
- .join(' '), style: { ...surfaceSlots(color, 0), ...style }, ...props, children: children }) })] }) }));
77
- }
1
+ "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Dialog as s}from"@base-ui/react/dialog";import{surfaceSlots as l}from"../../internal/styles.js";const r={scrim:"bg-(--plass-scrim) [backdrop-filter:blur(2px)] [-webkit-backdrop-filter:blur(2px)]",glass:/* @__PURE__ */["[background-color:color-mix(in_oklab,var(--plass-scrim)_45%,transparent)]","[backdrop-filter:var(--plass-blur)] [-webkit-backdrop-filter:var(--plass-blur)]"].join(" "),solid:"bg-(--plass-surface)",clear:""},i={start:"items-start",center:"items-center",end:"items-end"},t={xs:"p-3",sm:"p-4",md:"p-6",lg:"p-8",xl:"p-10"},n=/* @__PURE__ */["[transition:opacity_var(--plass-duration)_var(--plass-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" ");export function PlOverlay({open:o,defaultOpen:c,onOpenChange:p,tone:m="scrim",dismissible:d=!1,modal:f=!0,align:u="center",size:b="md",color:x="primary",label:y="Overlay",className:g,style:j,children:k,...h}){return e(s.Root,{open:o,defaultOpen:c,modal:f,disablePointerDismissal:!d,onOpenChange:(e,a)=>{d||e||"escape-key"!==a.reason?p?.(e):a.cancel()},children:a(s.Portal,{children:[e(s.Backdrop,{className:`plass-portal fixed inset-0 z-50 ${n} ${r[m]}`}),e(s.Viewport,{className:["plass-portal fixed inset-0 z-50 flex justify-center",i[u],t[b]].join(" "),children:e(s.Popup,{"aria-label":y,className:["flex max-h-full max-w-full flex-col items-center justify-center","[outline:none]",n,g??""].filter(Boolean).join(" "),style:{...l(x,0),...j},...h,children:k})})]})})}
@@ -1 +1 @@
1
- export { PlOverlay } from './PlOverlay.js';
1
+ export{PlOverlay}from"./PlOverlay.js";
@@ -1,159 +1 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import * as React from 'react';
3
- import { PlButton } from '../button/PlButton.js';
4
- import { ChevronIcon } from '../../internal/icons.js';
5
- import { controlTextClasses, gapClasses, srOnlyClasses } from '../../internal/styles.js';
6
- function range(start, end) {
7
- return Array.from({ length: Math.max(0, end - start + 1) }, (_, index) => start + index);
8
- }
9
- /**
10
- * Which pages the row actually shows.
11
- *
12
- * The shape every pagination converges on — a fixed run at each end, a window
13
- * around the current page, and an ellipsis wherever those leave a gap — with one
14
- * detail that is easy to get wrong and matters: a gap of exactly one page is
15
- * filled with that page rather than with an ellipsis. `1 … 3 … 9` hides a single
16
- * number behind a symbol wider than the number it replaced.
17
- *
18
- * The row is also pinned to a constant number of slots, whatever page it is on:
19
- * the window slides toward whichever end it is near instead of being clipped by
20
- * it, so page 1 shows `1 2 3 4 5 … 20` and page 10 shows `1 … 9 10 11 … 20`.
21
- * Which slots are pages and which are ellipses changes; how many there are does
22
- * not. Without that, stepping from page 1 to page 2 would relayout the row and
23
- * every button would move out from under the pointer that just pressed one.
24
- */
25
- function paginationRange(count, page, siblingCount, boundaryCount) {
26
- const startPages = range(1, Math.min(boundaryCount, count));
27
- const endPages = range(Math.max(count - boundaryCount + 1, boundaryCount + 1), count);
28
- const siblingsStart = Math.max(Math.min(page - siblingCount, count - boundaryCount - siblingCount * 2 - 1), boundaryCount + 2);
29
- const siblingsEnd = Math.min(Math.max(page + siblingCount, boundaryCount + siblingCount * 2 + 2), endPages.length > 0 ? endPages[0] - 2 : count - 1);
30
- return [
31
- ...startPages,
32
- // An ellipsis when more than one page is hidden, the page itself when
33
- // exactly one is, and nothing when none is.
34
- ...(siblingsStart > boundaryCount + 2
35
- ? ['start-ellipsis']
36
- : boundaryCount + 1 < count - boundaryCount
37
- ? [boundaryCount + 1]
38
- : []),
39
- ...range(siblingsStart, siblingsEnd),
40
- ...(siblingsEnd < count - boundaryCount - 1
41
- ? ['end-ellipsis']
42
- : count - boundaryCount > boundaryCount
43
- ? [count - boundaryCount]
44
- : []),
45
- ...endPages
46
- ];
47
- }
48
- /** Two chevrons, for the steppers that jump to an end rather than by one page. */
49
- function DoubleChevronIcon() {
50
- return (_jsx("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "m7.5 4.5 3.5 3.5-3.5 3.5M3.5 4.5 7 8l-3.5 3.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
51
- }
52
- /**
53
- * The ellipsis. A `<span>`, not a button and not a disabled button: it is not a
54
- * control that happens to be unavailable, it is punctuation.
55
- */
56
- const ellipsisClasses = {
57
- xs: 'h-6 min-w-6',
58
- sm: 'h-8 min-w-8',
59
- md: 'h-10 min-w-10',
60
- lg: 'h-12 min-w-12',
61
- xl: 'h-14 min-w-14'
62
- };
63
- /**
64
- * A row of page numbers.
65
- *
66
- * Every button in it is a real `PlButton`, which is the point: a pagination is
67
- * not a new kind of control, it is buttons in a row that happen to know about
68
- * each other. Reusing the component means the row inherits the glass, the
69
- * pointer bloom, the press signature, the focus ring and every future change to
70
- * any of them for free — and it means an `lg` pagination lines up with an `lg`
71
- * button beside it, because it *is* one.
72
- *
73
- * `variant` sets how the pages at rest look; the current page is always `solid`,
74
- * which is the one thing the row has to say without being read. That is why the
75
- * default here is `ghost` rather than the `solid` a lone PlButton takes — nine
76
- * panes of tinted glass in a row say that all nine are the primary action.
77
- *
78
- * The markup is a `<nav>` around a `<ul>` because that is what a screen reader
79
- * needs to hear: a named landmark it can skip, holding a list whose length says
80
- * how far the pages go, with `aria-current="page"` marking where it is.
81
- */
82
- export const PlPagination = /* @__PURE__ */ React.forwardRef(function PlPagination({ variant = 'ghost', size = 'md', color = 'primary', density = 'compact', elevation = 0, count, page: pageProp, defaultPage = 1, onPageChange, siblingCount = 1, boundaryCount = 1, showEdges = false, showArrows = true, disabled = false, getPageHref, label = 'Pagination', pageLabel = (value) => `Page ${value}`, previousLabel = 'Previous page', nextLabel = 'Next page', firstLabel = 'First page', lastLabel = 'Last page', statusLabel = (value, total) => `Page ${value} of ${total}`, className, children, ...props }, ref) {
83
- const [uncontrolled, setUncontrolled] = React.useState(defaultPage);
84
- const current = Math.min(Math.max(pageProp ?? uncontrolled, 1), Math.max(count, 1));
85
- const go = (next) => {
86
- const clamped = Math.min(Math.max(next, 1), count);
87
- if (clamped === current) {
88
- return;
89
- }
90
- if (pageProp === undefined) {
91
- setUncontrolled(clamped);
92
- }
93
- onPageChange?.(clamped);
94
- };
95
- // One page is not a set of pages, and no pages is not a thing to say out
96
- // loud. A row that renders a lone disabled "1" is a control advertising
97
- // that it has nothing to do.
98
- if (count < 2) {
99
- return null;
100
- }
101
- const slots = paginationRange(count, current, siblingCount, boundaryCount);
102
- const atStart = current <= 1;
103
- const atEnd = current >= count;
104
- /*
105
- * A link only where there is somewhere to go. The page being read and a
106
- * stepper at the end of the row are both `disabled`, and `disabled` is not
107
- * something an `<a>` can be — a link that only looks unavailable is one a
108
- * keyboard still lands on and a crawler still follows.
109
- */
110
- const linkProps = (to, inert, rel) => getPageHref && !inert ? { render: _jsx("a", { href: getPageHref(to), rel: rel }) } : null;
111
- /*
112
- * Who answers the press.
113
- *
114
- * With an `href` and a handler both, the handler wins and the navigation is
115
- * cancelled: that is a client-side router keeping the page it already has.
116
- * With an `href` and no handler, the link is left to do what a link does —
117
- * which is also what makes the row work with JavaScript still loading.
118
- */
119
- const press = (event, to) => {
120
- // A press carrying a modifier is the reader asking the browser for it: a
121
- // new tab, a new window, a saved copy. Never ours to cancel.
122
- if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
123
- return;
124
- }
125
- if (getPageHref && !onPageChange) {
126
- return;
127
- }
128
- event.preventDefault();
129
- go(to);
130
- };
131
- /**
132
- * The steppers. Icon-only PlButtons, so they go square and land on exactly
133
- * the same footprint as a single-digit page — a row whose ends are a
134
- * different width from its middle reads as two controls pushed together.
135
- */
136
- const stepper = (key, accessibleName, to, inert, rotation, glyph, rel) => (_jsx("li", { className: "flex", children: _jsx(PlButton, { variant: variant, size: size, color: color, density: density, elevation: elevation, disabled: disabled || inert, "aria-label": accessibleName, startIcon: _jsx("span", { className: `flex items-center ${rotation}`, children: glyph }), onClick: (event) => press(event, to), ...linkProps(to, disabled || inert, rel) }) }, key));
137
- return (_jsxs("nav", { ref: ref, "aria-label": label, className: ['flex items-center', className ?? ''].filter(Boolean).join(' '), ...props, children: [_jsxs("ul", { role: "list", className: `m-0 flex list-none items-center p-0 ${gapClasses[size]}`, children: [showEdges
138
- ? stepper('first', firstLabel, 1, atStart, 'rotate-180 rtl:rotate-0', _jsx(DoubleChevronIcon, {}))
139
- : null, showArrows
140
- ? stepper('previous', previousLabel, current - 1, atStart, 'rotate-90 rtl:-rotate-90', _jsx(ChevronIcon, {}), 'prev')
141
- : null, slots.map((slot, index) => typeof slot === 'number' ? (_jsx("li", { className: "flex", children: _jsx(PlButton
142
- // The current page is always filled, whatever the row's
143
- // resting variant is: it is the one thing here that has to be
144
- // legible without being read.
145
- , {
146
- // The current page is always filled, whatever the row's
147
- // resting variant is: it is the one thing here that has to be
148
- // legible without being read.
149
- variant: slot === current ? 'solid' : variant, size: size, color: color, density: density, elevation: elevation, disabled: disabled, "aria-label": pageLabel(slot), "aria-current": slot === current ? 'page' : undefined, className: "tabular-nums", onClick: (event) => press(event, slot), ...linkProps(slot, disabled || slot === current), children: slot }) }, `slot-${index}`)) : (_jsx("li", { "aria-hidden": "true", className: [
150
- 'flex select-none items-center justify-center',
151
- 'text-(--plass-muted-fg)',
152
- controlTextClasses[size],
153
- ellipsisClasses[size]
154
- ].join(' '), children: "\u2026" }, `slot-${index}`))), showArrows
155
- ? stepper('next', nextLabel, current + 1, atEnd, '-rotate-90 rtl:rotate-90', _jsx(ChevronIcon, {}), 'next')
156
- : null, showEdges
157
- ? stepper('last', lastLabel, count, atEnd, 'rtl:rotate-180', _jsx(DoubleChevronIcon, {}))
158
- : null] }), _jsx("span", { className: srOnlyClasses, "aria-live": "polite", children: statusLabel(current, count) }), children] }));
159
- });
1
+ "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{PlButton as n}from"../button/PlButton.js";import{ChevronIcon as r}from"../../internal/icons.js";import{controlTextClasses as l,gapClasses as i,srOnlyClasses as o}from"../../internal/styles.js";function range(e,a){return Array.from({length:Math.max(0,a-e+1)},(a,t)=>e+t)}function DoubleChevronIcon(){return e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:e("path",{d:"m7.5 4.5 3.5 3.5-3.5 3.5M3.5 4.5 7 8l-3.5 3.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}const s={xs:"h-6 min-w-6",sm:"h-8 min-w-8",md:"h-10 min-w-10",lg:"h-12 min-w-12",xl:"h-14 min-w-14"};export const PlPagination=/* @__PURE__ */t.forwardRef(function PlPagination({variant:c="ghost",size:m="md",color:u="primary",density:h="compact",elevation:d=0,count:f,page:g,defaultPage:p=1,onPageChange:x,siblingCount:b=1,boundaryCount:v=1,showEdges:y=!1,showArrows:M=!0,disabled:P=!1,getPageHref:j,label:w="Pagination",pageLabel:N=e=>`Page ${e}`,previousLabel:C="Previous page",nextLabel:L="Next page",firstLabel:k="First page",lastLabel:$="Last page",statusLabel:D=(e,a)=>`Page ${e} of ${a}`,className:I,children:K,...z},B){const[A,R]=t.useState(p),E=Math.min(Math.max(g??A,1),Math.max(f,1));if(f<2)return null;const F=function paginationRange(e,a,t,n){const r=range(1,Math.min(n,e)),l=range(Math.max(e-n+1,n+1),e),i=Math.max(Math.min(a-t,e-n-2*t-1),n+2),o=Math.min(Math.max(a+t,n+2*t+2),l.length>0?l[0]-2:e-1);return[...r,...i>n+2?["start-ellipsis"]:n+1<e-n?[n+1]:[],...range(i,o),...o<e-n-1?["end-ellipsis"]:e-n>n?[e-n]:[],...l]}(f,E,b,v),H=E<=1,S=E>=f,linkProps=(a,t,n)=>j&&!t?{render:e("a",{href:j(a),rel:n})}:null,press=(e,a)=>{e.metaKey||e.ctrlKey||e.shiftKey||e.altKey||j&&!x||(e.preventDefault(),(e=>{const a=Math.min(Math.max(e,1),f);a!==E&&(void 0===g&&R(a),x?.(a))})(a))},stepper=(a,t,r,l,i,o,s)=>e("li",{className:"flex",children:e(n,{variant:c,size:m,color:u,density:h,elevation:d,disabled:P||l,"aria-label":t,startIcon:e("span",{className:`flex items-center ${i}`,children:o}),onClick:e=>press(e,r),...linkProps(r,P||l,s)})},a);return a("nav",{ref:B,"aria-label":w,className:["flex items-center",I??""].filter(Boolean).join(" "),...z,children:[a("ul",{role:"list",className:`m-0 flex list-none items-center p-0 ${i[m]}`,children:[y?stepper("first",k,1,H,"rotate-180 rtl:rotate-0",e(DoubleChevronIcon,{})):null,M?stepper("previous",C,E-1,H,"rotate-90 rtl:-rotate-90",e(r,{}),"prev"):null,F.map((a,t)=>e("li","number"==typeof a?{className:"flex",children:e(n,{variant:a===E?"solid":c,size:m,color:u,density:h,elevation:d,disabled:P,"aria-label":N(a),"aria-current":a===E?"page":void 0,className:"tabular-nums",onClick:e=>press(e,a),...linkProps(a,P||a===E),children:a})}:{"aria-hidden":"true",className:["flex select-none items-center justify-center","text-(--plass-muted-fg)",l[m],s[m]].join(" "),children:"…"},`slot-${t}`)),M?stepper("next",L,E+1,S,"-rotate-90 rtl:rotate-90",e(r,{}),"next"):null,y?stepper("last",$,f,S,"rtl:rotate-180",e(DoubleChevronIcon,{})):null]}),e("span",{className:o,"aria-live":"polite",children:D(E,f)}),K]})});
@@ -1 +1 @@
1
- export { PlPagination } from './PlPagination.js';
1
+ export{PlPagination}from"./PlPagination.js";