plass-ui 1.0.0 → 1.0.1

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 (164) hide show
  1. package/dist/components/accordion/PlAccordion.js +1 -131
  2. package/dist/components/accordion/index.js +1 -1
  3. package/dist/components/alert/PlAlert.js +1 -109
  4. package/dist/components/alert/index.js +1 -1
  5. package/dist/components/animate-appear/PlAnimateAppear.js +1 -71
  6. package/dist/components/animate-appear/index.js +1 -1
  7. package/dist/components/animate-blink/PlAnimateBlink.js +1 -47
  8. package/dist/components/animate-blink/index.js +1 -1
  9. package/dist/components/animate-fade/PlAnimateFade.js +1 -48
  10. package/dist/components/animate-fade/index.js +1 -1
  11. package/dist/components/animate-grow/PlAnimateGrow.js +1 -49
  12. package/dist/components/animate-grow/index.js +1 -1
  13. package/dist/components/animate-headline/PlAnimateHeadline.js +1 -120
  14. package/dist/components/animate-headline/index.js +1 -1
  15. package/dist/components/animate-lighting/PlAnimateLighting.js +1 -65
  16. package/dist/components/animate-lighting/index.js +1 -1
  17. package/dist/components/animate-marquee/PlAnimateMarquee.js +1 -94
  18. package/dist/components/animate-marquee/index.js +1 -1
  19. package/dist/components/animate-rotate/PlAnimateRotate.js +1 -50
  20. package/dist/components/animate-rotate/index.js +1 -1
  21. package/dist/components/animate-slide/PlAnimateSlide.js +1 -49
  22. package/dist/components/animate-slide/index.js +1 -1
  23. package/dist/components/animate-typing/PlAnimateTyping.js +1 -177
  24. package/dist/components/animate-typing/index.js +1 -1
  25. package/dist/components/animate-zoom/PlAnimateZoom.js +1 -45
  26. package/dist/components/animate-zoom/index.js +1 -1
  27. package/dist/components/aspect-ratio/PlAspectRatio.js +1 -58
  28. package/dist/components/aspect-ratio/index.js +1 -1
  29. package/dist/components/avatar/PlAvatar.js +1 -121
  30. package/dist/components/avatar/index.js +1 -1
  31. package/dist/components/badge/PlBadge.js +1 -168
  32. package/dist/components/badge/index.js +1 -1
  33. package/dist/components/blockquote/PlBlockquote.js +1 -112
  34. package/dist/components/blockquote/index.js +1 -1
  35. package/dist/components/bottom-navigation/PlBottomNavigation.js +1 -141
  36. package/dist/components/bottom-navigation/index.js +1 -1
  37. package/dist/components/box/PlBox.js +1 -46
  38. package/dist/components/box/index.js +1 -1
  39. package/dist/components/breadcrumb/PlBreadcrumb.js +1 -201
  40. package/dist/components/breadcrumb/index.js +1 -1
  41. package/dist/components/button/PlButton.js +1 -196
  42. package/dist/components/button/index.js +1 -1
  43. package/dist/components/button-group/PlButtonGroup.js +1 -64
  44. package/dist/components/button-group/index.js +1 -1
  45. package/dist/components/card/PlCard.js +1 -102
  46. package/dist/components/card/index.js +1 -1
  47. package/dist/components/carousel/PlCarousel.js +1 -177
  48. package/dist/components/carousel/index.js +1 -1
  49. package/dist/components/chat-bubble/PlChatBubble.js +1 -206
  50. package/dist/components/chat-bubble/index.js +1 -1
  51. package/dist/components/checkbox/PlCheckbox.js +1 -100
  52. package/dist/components/checkbox/index.js +1 -1
  53. package/dist/components/chip/PlChip.js +1 -144
  54. package/dist/components/chip/index.js +1 -1
  55. package/dist/components/collapsible/PlCollapsible.js +1 -65
  56. package/dist/components/collapsible/index.js +1 -1
  57. package/dist/components/combobox/PlCombobox.js +1 -199
  58. package/dist/components/combobox/index.js +1 -1
  59. package/dist/components/container/PlContainer.js +1 -47
  60. package/dist/components/container/index.js +1 -1
  61. package/dist/components/date-picker/PlDatePicker.js +1 -87
  62. package/dist/components/date-picker/index.js +1 -1
  63. package/dist/components/date-range-picker/PlDateRangePicker.js +1 -152
  64. package/dist/components/date-range-picker/index.js +1 -1
  65. package/dist/components/date-time-picker/PlDateTimePicker.js +1 -106
  66. package/dist/components/date-time-picker/index.js +1 -1
  67. package/dist/components/divider/PlDivider.js +1 -107
  68. package/dist/components/divider/index.js +1 -1
  69. package/dist/components/drawer/PlDrawer.js +1 -190
  70. package/dist/components/drawer/index.js +1 -1
  71. package/dist/components/file-picker/PlFilePicker.js +1 -274
  72. package/dist/components/file-picker/index.js +1 -1
  73. package/dist/components/floating-bottom-navigation/PlFloatingBottomNavigation.js +1 -291
  74. package/dist/components/floating-bottom-navigation/index.js +1 -1
  75. package/dist/components/grid/PlGrid.js +1 -51
  76. package/dist/components/grid/PlGridItem.js +1 -34
  77. package/dist/components/grid/index.js +1 -2
  78. package/dist/components/highlight/PlHighlight.js +1 -185
  79. package/dist/components/highlight/index.js +1 -1
  80. package/dist/components/hot-keys/PlHotKeys.js +1 -294
  81. package/dist/components/hot-keys/index.js +1 -1
  82. package/dist/components/icon/PlIcon.js +1 -58
  83. package/dist/components/icon/index.js +1 -1
  84. package/dist/components/icon-button/PlIconButton.js +1 -37
  85. package/dist/components/icon-button/index.js +1 -1
  86. package/dist/components/list/PlList.js +1 -160
  87. package/dist/components/list/index.js +1 -1
  88. package/dist/components/menu/PlMenu.js +1 -209
  89. package/dist/components/menu/index.js +1 -1
  90. package/dist/components/modal/PlModal.js +1 -150
  91. package/dist/components/modal/index.js +1 -1
  92. package/dist/components/number-field/PlNumberField.js +1 -111
  93. package/dist/components/number-field/index.js +1 -1
  94. package/dist/components/otp-field/PlOtpField.js +1 -109
  95. package/dist/components/otp-field/index.js +1 -1
  96. package/dist/components/overlay/PlOverlay.js +1 -77
  97. package/dist/components/overlay/index.js +1 -1
  98. package/dist/components/pagination/PlPagination.js +1 -159
  99. package/dist/components/pagination/index.js +1 -1
  100. package/dist/components/panes/PlPanes.js +1 -324
  101. package/dist/components/panes/index.js +1 -1
  102. package/dist/components/pill/PlPill.js +1 -154
  103. package/dist/components/pill/index.js +1 -1
  104. package/dist/components/popover/PlPopover.js +1 -113
  105. package/dist/components/popover/index.js +1 -1
  106. package/dist/components/progress-box/PlProgressBox.js +1 -34
  107. package/dist/components/progress-box/index.js +1 -1
  108. package/dist/components/progress-circular/PlProgressCircular.js +1 -47
  109. package/dist/components/progress-circular/index.js +1 -1
  110. package/dist/components/progress-linear/PlProgressLinear.js +1 -40
  111. package/dist/components/progress-linear/index.js +1 -1
  112. package/dist/components/radio-group/PlRadioGroup.js +1 -99
  113. package/dist/components/radio-group/index.js +1 -1
  114. package/dist/components/rating/PlRating.js +1 -101
  115. package/dist/components/rating/index.js +1 -1
  116. package/dist/components/scroll-zone/PlScrollZone.js +1 -411
  117. package/dist/components/scroll-zone/index.js +1 -1
  118. package/dist/components/segmented-button/PlSegmentedButton.js +1 -206
  119. package/dist/components/segmented-button/index.js +1 -1
  120. package/dist/components/select/PlSelect.js +1 -115
  121. package/dist/components/select/index.js +1 -1
  122. package/dist/components/skeleton/PlSkeleton.js +1 -142
  123. package/dist/components/skeleton/index.js +1 -1
  124. package/dist/components/slider/PlSlider.js +1 -132
  125. package/dist/components/slider/index.js +1 -1
  126. package/dist/components/spoiler/PlSpoiler.js +1 -74
  127. package/dist/components/spoiler/index.js +1 -1
  128. package/dist/components/switch/PlSwitch.js +1 -131
  129. package/dist/components/switch/index.js +1 -1
  130. package/dist/components/table/PlTable.js +1 -210
  131. package/dist/components/table/index.js +1 -1
  132. package/dist/components/tabs/PlTabs.js +1 -182
  133. package/dist/components/tabs/index.js +1 -1
  134. package/dist/components/text-field/PlTextField.js +1 -126
  135. package/dist/components/text-field/index.js +1 -1
  136. package/dist/components/text-link/PlTextLink.js +1 -136
  137. package/dist/components/text-link/index.js +1 -1
  138. package/dist/components/time-picker/PlTimePicker.js +1 -97
  139. package/dist/components/time-picker/index.js +1 -1
  140. package/dist/components/timeline/PlTimeline.js +1 -207
  141. package/dist/components/timeline/index.js +1 -1
  142. package/dist/components/toast/PlToast.js +1 -174
  143. package/dist/components/toast/index.js +1 -1
  144. package/dist/components/toolbar/PlToolbar.js +1 -65
  145. package/dist/components/toolbar/index.js +1 -1
  146. package/dist/components/tooltip/PlTooltip.js +1 -117
  147. package/dist/components/tooltip/index.js +1 -1
  148. package/dist/components/typography/PlTypography.js +1 -143
  149. package/dist/components/typography/index.js +1 -1
  150. package/dist/index.js +1 -75
  151. package/dist/internal/animate.js +1 -318
  152. package/dist/internal/button-group.js +2 -19
  153. package/dist/internal/calendar.js +1 -501
  154. package/dist/internal/date.js +1 -353
  155. package/dist/internal/format.js +1 -41
  156. package/dist/internal/grid.js +1 -143
  157. package/dist/internal/icons.js +1 -138
  158. package/dist/internal/menu.js +1 -18
  159. package/dist/internal/picker.js +1 -139
  160. package/dist/internal/progress.js +1 -167
  161. package/dist/internal/sizer.js +1 -35
  162. package/dist/internal/styles.js +1 -636
  163. package/dist/types.js +0 -8
  164. package/package.json +3 -2
@@ -1,121 +1 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import * as React from 'react';
3
- import { Avatar as BaseUIAvatar } from '@base-ui/react/avatar';
4
- import { controlHeightClasses, controlSlots, controlSquareClasses, glassClasses, hasContent, radiusClasses, srOnlyClasses, transitionClasses } from '../../internal/styles.js';
5
- /**
6
- * The initials, sized off the box rather than off the row.
7
- *
8
- * Its own ladder and not `controlTextClasses`, because a control's label is
9
- * measured against the words next to it and this one is measured against the
10
- * circle around it: roughly 40% of the diameter at every step, which is where
11
- * two characters fill the width without touching the edge.
12
- */
13
- const initialsTextClasses = {
14
- xs: 'text-[0.5625rem]',
15
- sm: 'text-[0.6875rem]',
16
- md: 'text-[0.8125rem]',
17
- lg: 'text-[1rem]',
18
- xl: 'text-[1.1875rem]'
19
- };
20
- /**
21
- * The three materials, said the way a *control* says them: an avatar **is** the
22
- * thing being coloured — a portrait of one particular person — so its sheet
23
- * takes the tint, exactly as a `PlAlert`'s does and unlike a `PlCard`'s.
24
- *
25
- * `solid` carries no gloss line, for the reason a filled `PlButton` carries
26
- * none: the gradient is the form.
27
- */
28
- const variantClasses = {
29
- solid: /* @__PURE__ */ [
30
- 'text-(--p-on-solid) [background-image:var(--p-fill)]',
31
- '[box-shadow:var(--p-elev),var(--p-lift)]'
32
- ].join(' '),
33
- glass: /* @__PURE__ */ [
34
- glassClasses,
35
- 'border text-(--p-accent) bg-(--plass-glass)',
36
- '[border-color:var(--plass-border)]',
37
- '[box-shadow:var(--p-elev),var(--plass-gloss-glass)]'
38
- ].join(' '),
39
- ghost: 'text-(--p-accent) bg-(--p-soft-press) [box-shadow:var(--p-elev)]'
40
- };
41
- const baseClasses = /* @__PURE__ */ [
42
- 'relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden',
43
- 'align-middle leading-none font-semibold tracking-wide whitespace-nowrap',
44
- // A glyph handed to `children` is drawn against the circle, not against a
45
- // word, so it is sized off the box like the initials are rather than off the
46
- // `1.2em` an icon riding on a label takes.
47
- '[&_svg]:pointer-events-none [&_svg]:size-[55%]',
48
- transitionClasses
49
- ].join(' ');
50
- /**
51
- * The default fallback: a shoulders-and-head silhouette, drawn here rather than
52
- * in `internal/icons` because this is the only component that needs it.
53
- *
54
- * It exists so that `<PlAvatar />` with nothing at all is still an avatar. A box
55
- * with no picture, no name and no glyph in it is indistinguishable from a
56
- * component that failed to render.
57
- */
58
- function PersonIcon() {
59
- return (_jsxs("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: [_jsx("path", { d: "M12 12a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Z" }), _jsx("path", { d: "M12 14.25c-4.28 0-7.75 2.42-7.75 5.4 0 .75.6 1.35 1.35 1.35h12.8c.75 0 1.35-.6 1.35-1.35 0-2.98-3.47-5.4-7.75-5.4Z" })] }));
60
- }
61
- /**
62
- * The first character of the first word, plus the first of the last.
63
- *
64
- * `Array.from` rather than `[0]`, so a name that starts with an emoji or with
65
- * any character outside the basic plane is not cut in half between its two code
66
- * units. `normalize('NFC')` first, so a name whose accents arrived decomposed —
67
- * which is what a macOS filename and a good many APIs hand you — yields `Ä`
68
- * rather than a bare `A`.
69
- *
70
- * One word gives one character on purpose. Korean, Japanese and Chinese names
71
- * are a single token, and two of their characters at 40px is a smudge where one
72
- * is a name.
73
- */
74
- function initialsOf(name) {
75
- const words = name.normalize('NFC').trim().split(/\s+/).filter(Boolean);
76
- if (words.length === 0) {
77
- return '';
78
- }
79
- const first = Array.from(words[0])[0] ?? '';
80
- const last = words.length > 1 ? (Array.from(words[words.length - 1])[0] ?? '') : '';
81
- return (first + last).toLocaleUpperCase();
82
- }
83
- /**
84
- * A picture of a person or a thing, at a known size, that is never an empty box.
85
- *
86
- * Three things can be drawn in it and exactly one of them is at a time: the
87
- * picture, if `src` is given and it loads; otherwise whatever stands in for it —
88
- * `children`, or `initials`, or the initials derived from `name`; and failing
89
- * all of those, a silhouette. Which one is showing is Base UI's `Avatar` to
90
- * decide, because "has the image loaded" is a question with four answers and a
91
- * race in the middle of it.
92
- *
93
- * It carries no status dot of its own. An avatar with a green mark on it is a
94
- * `PlBadge` with an avatar in it, and inventing a second spelling for that would
95
- * give the library two of them.
96
- */
97
- export const PlAvatar = /* @__PURE__ */ React.forwardRef(function PlAvatar({ src, srcSet, alt, name, initials, shape = 'circle', variant = 'ghost', size = 'md', color = 'primary', elevation = 0, delay, imageProps, onLoadingStatusChange, className, style, children, ...props }, ref) {
98
- const derived = name ? initialsOf(name) : '';
99
- const label = alt ?? name;
100
- // `children` beats the initials beats the silhouette. Only the last of the
101
- // three has nothing to say, which is what decides whether the fallback needs
102
- // the name spelled out beside it.
103
- const stand = hasContent(children) ? children : (initials ?? derived) || _jsx(PersonIcon, {});
104
- const speaks = hasContent(children) || Boolean(initials ?? derived);
105
- const classNames = [
106
- baseClasses,
107
- controlHeightClasses[size],
108
- controlSquareClasses[size],
109
- initialsTextClasses[size],
110
- shape === 'circle' ? 'rounded-full' : radiusClasses[size],
111
- variantClasses[variant],
112
- className ?? ''
113
- ]
114
- .filter(Boolean)
115
- .join(' ');
116
- return (_jsxs(BaseUIAvatar.Root, { ref: ref, className: classNames, style: { ...controlSlots(color, elevation, variant), ...style }, ...props, children: [src ? (_jsx(BaseUIAvatar.Image, { src: src, srcSet: srcSet,
117
- // Empty rather than absent: an avatar beside the person's own name is
118
- // decoration, and `alt` left off is what makes a screen reader read
119
- // the file name out instead.
120
- alt: label ?? '', className: "size-full object-cover", onLoadingStatusChange: onLoadingStatusChange, ...imageProps })) : null, _jsxs(BaseUIAvatar.Fallback, { delay: src ? delay : undefined, className: "flex size-full items-center justify-center", children: [label && speaks ? _jsx("span", { className: srOnlyClasses, children: label }) : null, _jsx("span", { "aria-hidden": label && speaks ? true : undefined, className: "contents", children: stand })] })] }));
121
- });
1
+ "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as r from"react";import{Avatar as t}from"@base-ui/react/avatar";import{controlHeightClasses as s,controlSlots as n,controlSquareClasses as l,glassClasses as o,hasContent as i,radiusClasses as c,srOnlyClasses as d,transitionClasses as m}from"../../internal/styles.js";const p={xs:"text-[0.5625rem]",sm:"text-[0.6875rem]",md:"text-[0.8125rem]",lg:"text-[1rem]",xl:"text-[1.1875rem]"},f={solid:/* @__PURE__ */["text-(--p-on-solid) [background-image:var(--p-fill)]","[box-shadow:var(--p-elev),var(--p-lift)]"].join(" "),glass:/* @__PURE__ */[o,"border text-(--p-accent) bg-(--plass-glass)","[border-color:var(--plass-border)]","[box-shadow:var(--p-elev),var(--plass-gloss-glass)]"].join(" "),ghost:"text-(--p-accent) bg-(--p-soft-press) [box-shadow:var(--p-elev)]"},g=/* @__PURE__ */["relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden","align-middle leading-none font-semibold tracking-wide whitespace-nowrap","[&_svg]:pointer-events-none [&_svg]:size-[55%]",m].join(" ");function PersonIcon(){return a("svg",{viewBox:"0 0 24 24",fill:"currentColor","aria-hidden":"true",children:[e("path",{d:"M12 12a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Z"}),e("path",{d:"M12 14.25c-4.28 0-7.75 2.42-7.75 5.4 0 .75.6 1.35 1.35 1.35h12.8c.75 0 1.35-.6 1.35-1.35 0-2.98-3.47-5.4-7.75-5.4Z"})]})}export const PlAvatar=/* @__PURE__ */r.forwardRef(function PlAvatar({src:r,srcSet:o,alt:m,name:v,initials:h,shape:u="circle",variant:x="ghost",size:b="md",color:j="primary",elevation:y=0,delay:w,imageProps:N,onLoadingStatusChange:z,className:A,style:C,children:P,...k},B){const S=v?function initialsOf(e){const a=e.normalize("NFC").trim().split(/\s+/).filter(Boolean);return 0===a.length?"":((Array.from(a[0])[0]??"")+(a.length>1?Array.from(a[a.length-1])[0]??"":"")).toLocaleUpperCase()}(v):"",I=m??v,L=i(P)?P:(h??S)||e(PersonIcon,{}),F=i(P)||Boolean(h??S),M=[g,s[b],l[b],p[b],"circle"===u?"rounded-full":c[b],f[x],A??""].filter(Boolean).join(" ");return a(t.Root,{ref:B,className:M,style:{...n(j,y,x),...C},...k,children:[r?e(t.Image,{src:r,srcSet:o,alt:I??"",className:"size-full object-cover",onLoadingStatusChange:z,...N}):null,a(t.Fallback,{delay:r?w:void 0,className:"flex size-full items-center justify-center",children:[I&&F?e("span",{className:d,children:I}):null,e("span",{"aria-hidden":!(!I||!F)||void 0,className:"contents",children:L})]})]})});
@@ -1 +1 @@
1
- export { PlAvatar } from './PlAvatar.js';
1
+ export{PlAvatar}from"./PlAvatar.js";
@@ -1,168 +1 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import * as React from 'react';
3
- import { controlSlots, glassClasses, hasContent, srOnlyClasses, transitionClasses } from '../../internal/styles.js';
4
- /**
5
- * A badge is smaller than anything else in the library, so it has a ladder of
6
- * its own rather than a step off `controlHeightClasses`.
7
- *
8
- * A control's height is the number a *row* lines up on; a badge lines up on
9
- * nothing — it hangs off the corner of something else. `md` is 18px, which is
10
- * the smallest a two-digit number stays legible at.
11
- */
12
- const badgeHeightClasses = {
13
- xs: 'h-3.5 min-w-3.5',
14
- sm: 'h-4 min-w-4',
15
- md: 'h-4.5 min-w-4.5',
16
- lg: 'h-5 min-w-5',
17
- xl: 'h-6 min-w-6'
18
- };
19
- /** The dot: the same ladder with the digits taken out, so it goes square. */
20
- const dotSizeClasses = {
21
- xs: 'size-1.5',
22
- sm: 'size-2',
23
- md: 'size-2.5',
24
- lg: 'size-2.5',
25
- xl: 'size-3'
26
- };
27
- const badgeTextClasses = {
28
- xs: 'text-[0.5625rem]',
29
- sm: 'text-[0.625rem]',
30
- md: 'text-[0.6875rem]',
31
- lg: 'text-[0.75rem]',
32
- xl: 'text-[0.8125rem]'
33
- };
34
- /** Horizontal breathing room around the digits. `density` is what halves it. */
35
- const badgePaddingClasses = {
36
- default: { xs: 'px-1', sm: 'px-1', md: 'px-1.5', lg: 'px-1.5', xl: 'px-2' },
37
- compact: { xs: 'px-0.5', sm: 'px-0.5', md: 'px-1', lg: 'px-1', xl: 'px-1.5' }
38
- };
39
- /**
40
- * A badge sits well below the radius ladder — at 18px tall, `--plass-radius-xs`
41
- * (8px) is already most of the way to a pill, and a badge *is* the one thing in
42
- * the library allowed to be one.
43
- *
44
- * That is not a hole in the design language, it is the exception the language
45
- * names. A Plass corner is a moulded fillet on a *surface*, and a badge is not a
46
- * surface: it is a mark laid on one — which is also why it is the only component
47
- * that overlaps its neighbour.
48
- */
49
- const badgeRadiusClasses = 'rounded-full';
50
- /**
51
- * How far the marker is pulled out of the corner, per size.
52
- *
53
- * A negative margin rather than the `translate(50%,-50%)` every other library
54
- * reaches for, because the house rule against `transform` is absolute and worth
55
- * more than the two lines it costs here. The offsets are half the marker's own
56
- * height, so the vertical overhang is exactly half — and horizontally a wide
57
- * `99+` tucks in a little further than half, which is what you want anyway.
58
- */
59
- const cornerOffsets = {
60
- xs: { badge: '-mt-1.5 -mb-1.5 -ms-1.5 -me-1.5', dot: '-mt-0.5 -mb-0.5 -ms-0.5 -me-0.5' },
61
- sm: { badge: '-mt-2 -mb-2 -ms-2 -me-2', dot: '-mt-1 -mb-1 -ms-1 -me-1' },
62
- md: { badge: '-mt-2 -mb-2 -ms-2 -me-2', dot: '-mt-1 -mb-1 -ms-1 -me-1' },
63
- lg: { badge: '-mt-2.5 -mb-2.5 -ms-2.5 -me-2.5', dot: '-mt-1 -mb-1 -ms-1 -me-1' },
64
- xl: { badge: '-mt-3 -mb-3 -ms-3 -me-3', dot: '-mt-1.5 -mb-1.5 -ms-1.5 -me-1.5' }
65
- };
66
- /**
67
- * Which two edges the marker is pinned to. Logical properties throughout, so the
68
- * corner flips with the writing direction rather than staying stuck on the right.
69
- */
70
- const placementClasses = {
71
- 'top-start': 'top-0 start-0',
72
- 'top-end': 'top-0 end-0',
73
- 'bottom-start': 'bottom-0 start-0',
74
- 'bottom-end': 'bottom-0 end-0'
75
- };
76
- /**
77
- * The extra inset a round anchor needs. A circle's corner is `r·(1 − 1/√2)` —
78
- * about 15% of its diameter — inside the bounding box the badge is positioned
79
- * against, so without this the marker floats off an avatar with a gap under it.
80
- */
81
- const circleInsetClasses = {
82
- 'top-start': 'mt-[7%] ms-[7%]',
83
- 'top-end': 'mt-[7%] me-[7%]',
84
- 'bottom-start': 'mb-[7%] ms-[7%]',
85
- 'bottom-end': 'mb-[7%] me-[7%]'
86
- };
87
- /**
88
- * The three materials, said the way a *control* says them: the marker is the
89
- * thing being coloured, so its sheet takes the tint.
90
- *
91
- * `solid` carries the gradient and the tinted lift and no gloss line, exactly as
92
- * a filled `PlButton` does. `ghost` is the one to reach for on a busy surface —
93
- * a soft tinted mark that reports without shouting.
94
- */
95
- const variantClasses = {
96
- solid: /* @__PURE__ */ [
97
- 'text-(--p-on-solid) [background-image:var(--p-fill)]',
98
- '[box-shadow:var(--p-elev),var(--p-lift)]'
99
- ].join(' '),
100
- glass: /* @__PURE__ */ [
101
- glassClasses,
102
- 'border text-(--p-accent) bg-(--plass-glass)',
103
- '[border-color:var(--plass-border)]',
104
- '[box-shadow:var(--p-elev),var(--plass-gloss-glass)]'
105
- ].join(' '),
106
- ghost: 'text-(--p-accent) bg-(--p-soft-press)'
107
- };
108
- /** `99+`, but only for a value a `+` means anything on. */
109
- function capContent(content, max) {
110
- return typeof content === 'number' && content > max ? `${max}+` : content;
111
- }
112
- /**
113
- * A small mark in the corner of something else: unread mail on an inbox icon, a
114
- * status dot on an avatar, a count on a tab.
115
- *
116
- * The shell is a `<span>` that wraps the anchor and does nothing but establish a
117
- * positioning context — no width, no padding, `align-middle` — so a badged icon
118
- * button still measures and lines up exactly like a bare one. With no children
119
- * the marker lays out inline instead, which is what a standalone status pill is.
120
- *
121
- * There is no Base UI primitive under this, and there should not be: a badge has
122
- * no interaction, no state and no keyboard contract. It is a mark. Wiring it to a
123
- * widget primitive would hand every decorative dot a role it cannot honour.
124
- *
125
- * What it does owe a screen reader is a sentence rather than a number, which is
126
- * what `label` is for — `content={3}` beside a bell reads out as "3".
127
- */
128
- export const PlBadge = /* @__PURE__ */ React.forwardRef(function PlBadge({ variant = 'solid', size = 'md', color = 'primary', density = 'default', elevation = 0, content, max = 99, dot = false, showZero = false, invisible = false, placement = 'top-end', overlap = 'square', label, className, style, children, ...props }, ref) {
129
- const anchored = hasContent(children);
130
- // `0` is content, and `hasContent` would agree — this is the one place the
131
- // library asks a second question, because a count of nothing is not news.
132
- const empty = !hasContent(content) || (content === 0 && !showZero);
133
- const asDot = dot || empty;
134
- const hidden = invisible || (empty && !dot);
135
- const markerClasses = [
136
- 'pointer-events-none z-10 inline-flex shrink-0 items-center justify-center',
137
- 'font-semibold tabular-nums whitespace-nowrap',
138
- badgeRadiusClasses,
139
- transitionClasses,
140
- variantClasses[variant],
141
- asDot
142
- ? dotSizeClasses[size]
143
- : [
144
- badgeHeightClasses[size],
145
- badgeTextClasses[size],
146
- badgePaddingClasses[density][size]
147
- ].join(' '),
148
- anchored ? `absolute ${placementClasses[placement]}` : 'relative align-middle',
149
- anchored ? (asDot ? cornerOffsets[size].dot : cornerOffsets[size].badge) : '',
150
- anchored && overlap === 'circle' ? circleInsetClasses[placement] : '',
151
- // Visibility, not opacity: a half-faded badge is a badge you have to squint
152
- // at to find out whether it is there. The marker keeps its box either way,
153
- // so nothing around it moves when it comes back.
154
- hidden ? 'invisible' : '',
155
- className ?? ''
156
- ]
157
- .filter(Boolean)
158
- .join(' ');
159
- const capped = capContent(content, max);
160
- const marker = (_jsx("span", { ref: ref, className: markerClasses, style: { ...controlSlots(color, elevation, variant), ...style }, "aria-hidden": hidden ? true : undefined, ...props, children: hidden ? null : (_jsxs(_Fragment, { children: [asDot || label ? _jsx("span", { className: srOnlyClasses, children: label ?? capped }) : null, asDot ? null : _jsx("span", { "aria-hidden": label ? true : undefined, children: capped })] })) }));
161
- if (!anchored) {
162
- return marker;
163
- }
164
- // `inline-flex` rather than `inline-block`: the shell has to be exactly as
165
- // wide and as tall as what it wraps, or a badged icon button stops lining up
166
- // with the bare one beside it.
167
- return (_jsxs("span", { className: "relative inline-flex shrink-0 align-middle", children: [children, marker] }));
168
- });
1
+ "use client";import{jsx as e,Fragment as t,jsxs as s}from"react/jsx-runtime";import*as m from"react";import{controlSlots as o,glassClasses as a,hasContent as l,srOnlyClasses as n,transitionClasses as r}from"../../internal/styles.js";const i={xs:"h-3.5 min-w-3.5",sm:"h-4 min-w-4",md:"h-4.5 min-w-4.5",lg:"h-5 min-w-5",xl:"h-6 min-w-6"},d={xs:"size-1.5",sm:"size-2",md:"size-2.5",lg:"size-2.5",xl:"size-3"},p={xs:"text-[0.5625rem]",sm:"text-[0.625rem]",md:"text-[0.6875rem]",lg:"text-[0.75rem]",xl:"text-[0.8125rem]"},b={default:{xs:"px-1",sm:"px-1",md:"px-1.5",lg:"px-1.5",xl:"px-2"},compact:{xs:"px-0.5",sm:"px-0.5",md:"px-1",lg:"px-1",xl:"px-1.5"}},x="rounded-full",c={xs:{badge:"-mt-1.5 -mb-1.5 -ms-1.5 -me-1.5",dot:"-mt-0.5 -mb-0.5 -ms-0.5 -me-0.5"},sm:{badge:"-mt-2 -mb-2 -ms-2 -me-2",dot:"-mt-1 -mb-1 -ms-1 -me-1"},md:{badge:"-mt-2 -mb-2 -ms-2 -me-2",dot:"-mt-1 -mb-1 -ms-1 -me-1"},lg:{badge:"-mt-2.5 -mb-2.5 -ms-2.5 -me-2.5",dot:"-mt-1 -mb-1 -ms-1 -me-1"},xl:{badge:"-mt-3 -mb-3 -ms-3 -me-3",dot:"-mt-1.5 -mb-1.5 -ms-1.5 -me-1.5"}},g={"top-start":"top-0 start-0","top-end":"top-0 end-0","bottom-start":"bottom-0 start-0","bottom-end":"bottom-0 end-0"},f={"top-start":"mt-[7%] ms-[7%]","top-end":"mt-[7%] me-[7%]","bottom-start":"mb-[7%] ms-[7%]","bottom-end":"mb-[7%] me-[7%]"},h={solid:/* @__PURE__ */["text-(--p-on-solid) [background-image:var(--p-fill)]","[box-shadow:var(--p-elev),var(--p-lift)]"].join(" "),glass:/* @__PURE__ */[a,"border text-(--p-accent) bg-(--plass-glass)","[border-color:var(--plass-border)]","[box-shadow:var(--p-elev),var(--plass-gloss-glass)]"].join(" "),ghost:"text-(--p-accent) bg-(--p-soft-press)"};export const PlBadge=/* @__PURE__ */m.forwardRef(function PlBadge({variant:m="solid",size:a="md",color:u="primary",density:v="default",elevation:w=0,content:j,max:y=99,dot:z=!1,showZero:N=!1,invisible:k=!1,placement:B="top-end",overlap:P="square",label:$,className:q,style:C,children:F,...R},Z){const A=l(F),D=!l(j)||0===j&&!N,E=z||D,G=k||D&&!z,H=["pointer-events-none z-10 inline-flex shrink-0 items-center justify-center","font-semibold tabular-nums whitespace-nowrap",x,r,h[m],E?d[a]:[i[a],p[a],b[v][a]].join(" "),A?`absolute ${g[B]}`:"relative align-middle",A?E?c[a].dot:c[a].badge:"",A&&"circle"===P?f[B]:"",G?"invisible":"",q??""].filter(Boolean).join(" "),I=function capContent(e,t){return"number"==typeof e&&e>t?`${t}+`:e}(j,y),J=e("span",{ref:Z,className:H,style:{...o(u,w,m),...C},"aria-hidden":!!G||void 0,...R,children:G?null:s(t,{children:[E||$?e("span",{className:n,children:$??I}):null,E?null:e("span",{"aria-hidden":!!$||void 0,children:I})]})});return A?s("span",{className:"relative inline-flex shrink-0 align-middle",children:[F,J]}):J});
@@ -1 +1 @@
1
- export { PlBadge } from './PlBadge.js';
1
+ export{PlBadge}from"./PlBadge.js";
@@ -1,112 +1 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import * as React from 'react';
3
- import { glassClasses, hasContent, metaTextClasses, radiusClasses, sheetPaddingXClasses, sheetPaddingYClasses, surfaceSlots, transitionClasses } from '../../internal/styles.js';
4
- /**
5
- * The quote itself, one step above body copy with the leading opened up.
6
- *
7
- * The sizes are `sheetTitleClasses`', because a quote is set at a heading's
8
- * scale — but the leading is not: a title is a line or two and a quote is a
9
- * paragraph somebody has to read, so it gets the air a paragraph needs.
10
- */
11
- const quoteTextClasses = {
12
- xs: 'text-[0.75rem]/[1.25rem]',
13
- sm: 'text-[0.8125rem]/[1.375rem]',
14
- md: 'text-[0.9375rem]/[1.625rem]',
15
- lg: 'text-[1.0625rem]/[1.875rem]',
16
- xl: 'text-[1.25rem]/[2.125rem]'
17
- };
18
- /**
19
- * The rule down the leading edge, and the one thing every variant has.
20
- *
21
- * `border-s`, not `border-l`: the rule belongs on the side the text starts on,
22
- * which is the right edge under RTL. Its width is the one number here that does
23
- * not come off a ladder — a quote rule is 2px at every size, because it is a
24
- * mark in the margin rather than a part of the type.
25
- */
26
- const ruleClasses = 'border-s-2 [border-inline-start-color:var(--p-accent)]';
27
- /**
28
- * The three materials, said the way a *container* says them — the sheet is never
29
- * dyed, exactly as on a `PlCard`. A quote holds somebody else's words, and words
30
- * on a tinted pane are words on a background nobody chose them against. The
31
- * family reaches the rule and stops.
32
- *
33
- * `ghost` is the default and the one that belongs in running prose: a rule in
34
- * the margin and nothing else, which is what a quote has looked like since long
35
- * before there were surfaces to put one on.
36
- */
37
- const variantClasses = {
38
- solid: /* @__PURE__ */ [
39
- glassClasses,
40
- 'bg-(--plass-glass-press)',
41
- '[box-shadow:var(--p-elev),var(--plass-gloss-glass)]'
42
- ].join(' '),
43
- // `border-s-2` again, after `border`, so the hairline on the other three edges
44
- // does not flatten the rule back to a pixel.
45
- glass: /* @__PURE__ */ [
46
- glassClasses,
47
- 'border border-s-2 bg-(--plass-glass)',
48
- '[border-color:var(--plass-glass-line)]',
49
- '[box-shadow:var(--p-elev),var(--plass-gloss-glass)]'
50
- ].join(' '),
51
- ghost: 'bg-transparent'
52
- };
53
- /**
54
- * The quotation mark: a pair of commas turned up, drawn rather than typed.
55
- *
56
- * A real `“` would be set in whatever face the page uses and would change shape,
57
- * weight and baseline with it — and at 2em it is the largest single glyph in the
58
- * component, so it changing is the most visible thing that could. This is one
59
- * drawing at one weight, and it lives here rather than in `internal/icons.tsx`
60
- * because exactly one component draws it.
61
- */
62
- function QuoteMarkIcon() {
63
- return (_jsx("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M6.4 3.6c-2.3.9-3.7 2.8-3.7 5.1 0 2 1.2 3.3 2.8 3.3 1.4 0 2.5-1 2.5-2.4 0-1.3-.9-2.2-2.1-2.2-.2 0-.4 0-.6.1.3-1 1.1-1.8 2.2-2.3l-1.1-1.6ZM13.3 3.6c-2.3.9-3.7 2.8-3.7 5.1 0 2 1.2 3.3 2.8 3.3 1.4 0 2.5-1 2.5-2.4 0-1.3-.9-2.2-2.1-2.2-.2 0-.4 0-.6.1.3-1 1.1-1.8 2.2-2.3l-1.1-1.6Z", fill: "currentColor" }) }));
64
- }
65
- /**
66
- * Somebody else's words, set apart from your own.
67
- *
68
- * There is no Base UI primitive under this and there should not be: a quote has
69
- * no state, no keyboard contract and nothing to interact with. What it has is
70
- * markup that is easy to get wrong, and getting it right is most of the point.
71
- *
72
- * **Nothing is drawn on the `<blockquote>` itself.** The surface, the rule and
73
- * the padding all belong to the element around it, and that is not tidiness —
74
- * `blockquote` is one of the handful of tags a host stylesheet still styles by
75
- * name. VitePress's `.vp-doc blockquote` sets a grey `border-left`, a
76
- * `padding-left` and a `color`, all at a specificity a one-class utility cannot
77
- * outrank, so a rule drawn on the quote itself would silently come out grey and
78
- * a pixel too thin. Moving the drawing onto a wrapper is what lets the docs undo
79
- * VitePress's version without also undoing this one.
80
- *
81
- * The wrapper is a `<figure>` when there is an attribution and a `<div>` when
82
- * there is not, because the HTML spec is explicit that the attribution goes
83
- * *outside* the blockquote — a name inside it claims the speaker said their own
84
- * name — and a `<figure>` with no `<figcaption>` in it is a figure of nothing.
85
- */
86
- export const PlBlockquote = /* @__PURE__ */ React.forwardRef(function PlBlockquote({ variant = 'ghost', size = 'md', color = 'primary', density = 'default', elevation = 0, author, source, cite, icon, className, style, children, ...props }, ref) {
87
- const attributed = hasContent(author) || hasContent(source);
88
- const glyph = icon === undefined ? _jsx(QuoteMarkIcon, {}) : icon;
89
- const shellClasses = [
90
- 'flex flex-col text-(--plass-fg)',
91
- ruleClasses,
92
- // The corners on the ruled edge stay square: a 2px rule that curves away
93
- // from the text it marks is a bracket, not a margin rule.
94
- variant === 'ghost' ? '' : `${radiusClasses[size]} rounded-s-none`,
95
- variantClasses[variant],
96
- sheetPaddingXClasses[density][size],
97
- sheetPaddingYClasses[density][size],
98
- transitionClasses,
99
- className ?? ''
100
- ]
101
- .filter(Boolean)
102
- .join(' ');
103
- const quote = (_jsxs("blockquote", { cite: cite, className: quoteTextClasses[size], children: [hasContent(glyph) ? (_jsx("span", { "aria-hidden": "true", className: "mb-1 block size-[2em] text-(--p-soft-press) [&>svg]:size-full", children: glyph })) : null, children] }));
104
- const shellStyle = { ...surfaceSlots(color, elevation), ...style };
105
- if (!attributed) {
106
- return (_jsx("div", { ref: ref, className: shellClasses, style: shellStyle, ...props, children: quote }));
107
- }
108
- return (_jsxs("figure", { ref: ref, className: shellClasses, style: shellStyle, ...props, children: [quote, _jsxs("figcaption", { className: [
109
- 'mt-2 flex flex-wrap items-baseline gap-x-1.5 text-(--plass-muted-fg)',
110
- metaTextClasses[size]
111
- ].join(' '), children: [hasContent(author) ? (_jsxs("span", { className: "font-medium text-(--plass-fg)", children: [_jsx("span", { "aria-hidden": "true", children: "\u2014 " }), author] })) : null, hasContent(source) ? _jsx("cite", { className: "not-italic", children: source }) : null] })] }));
112
- });
1
+ "use client";import{jsx as e,jsxs as s}from"react/jsx-runtime";import*as r from"react";import{glassClasses as l,hasContent as a,metaTextClasses as t,radiusClasses as o,sheetPaddingXClasses as n,sheetPaddingYClasses as i,surfaceSlots as c,transitionClasses as d}from"../../internal/styles.js";const m={xs:"text-[0.75rem]/[1.25rem]",sm:"text-[0.8125rem]/[1.375rem]",md:"text-[0.9375rem]/[1.625rem]",lg:"text-[1.0625rem]/[1.875rem]",xl:"text-[1.25rem]/[2.125rem]"},p="border-s-2 [border-inline-start-color:var(--p-accent)]",u={solid:/* @__PURE__ */[l,"bg-(--plass-glass-press)","[box-shadow:var(--p-elev),var(--plass-gloss-glass)]"].join(" "),glass:/* @__PURE__ */[l,"border border-s-2 bg-(--plass-glass)","[border-color:var(--plass-glass-line)]","[box-shadow:var(--p-elev),var(--plass-gloss-glass)]"].join(" "),ghost:"bg-transparent"};function QuoteMarkIcon(){return e("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:e("path",{d:"M6.4 3.6c-2.3.9-3.7 2.8-3.7 5.1 0 2 1.2 3.3 2.8 3.3 1.4 0 2.5-1 2.5-2.4 0-1.3-.9-2.2-2.1-2.2-.2 0-.4 0-.6.1.3-1 1.1-1.8 2.2-2.3l-1.1-1.6ZM13.3 3.6c-2.3.9-3.7 2.8-3.7 5.1 0 2 1.2 3.3 2.8 3.3 1.4 0 2.5-1 2.5-2.4 0-1.3-.9-2.2-2.1-2.2-.2 0-.4 0-.6.1.3-1 1.1-1.8 2.2-2.3l-1.1-1.6Z",fill:"currentColor"})})}export const PlBlockquote=/* @__PURE__ */r.forwardRef(function PlBlockquote({variant:r="ghost",size:l="md",color:f="primary",density:g="default",elevation:x=0,author:h,source:v,cite:b,icon:j,className:N,style:k,children:y,...w},B){const M=a(h)||a(v),q=void 0===j?e(QuoteMarkIcon,{}):j,z=["flex flex-col text-(--plass-fg)",p,"ghost"===r?"":`${o[l]} rounded-s-none`,u[r],n[g][l],i[g][l],d,N??""].filter(Boolean).join(" "),I=s("blockquote",{cite:b,className:m[l],children:[a(q)?e("span",{"aria-hidden":"true",className:"mb-1 block size-[2em] text-(--p-soft-press) [&>svg]:size-full",children:q}):null,y]}),P={...c(f,x),...k};return M?s("figure",{ref:B,className:z,style:P,...w,children:[I,s("figcaption",{className:["mt-2 flex flex-wrap items-baseline gap-x-1.5 text-(--plass-muted-fg)",t[l]].join(" "),children:[a(h)?s("span",{className:"font-medium text-(--plass-fg)",children:[e("span",{"aria-hidden":"true",children:"— "}),h]}):null,a(v)?e("cite",{className:"not-italic",children:v}):null]})]}):e("div",{ref:B,className:z,style:P,...w,children:I})});
@@ -1 +1 @@
1
- export { PlBlockquote } from './PlBlockquote.js';
1
+ export{PlBlockquote}from"./PlBlockquote.js";
@@ -1,141 +1 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import * as React from 'react';
3
- import { useRender } from '@base-ui/react/use-render';
4
- import { cx, focusRingInsetClasses, hasContent, iconSizeClasses, metaTextClasses, radiusClasses, sheetLineClasses, sheetRestClasses, srOnlyClasses, surfaceSlots, transitionClasses } from '../../internal/styles.js';
5
- const BottomNavigationContext = /* @__PURE__ */ React.createContext({
6
- value: null,
7
- change: () => { },
8
- size: 'md',
9
- density: 'default',
10
- labels: 'all',
11
- disabled: false
12
- });
13
- const positionClasses = {
14
- static: '',
15
- sticky: 'sticky bottom-0 z-20',
16
- fixed: 'fixed inset-x-0 bottom-0 z-30'
17
- };
18
- /**
19
- * The row's floor.
20
- *
21
- * `md` is 56px, which is the height a bottom navigation has had since the first
22
- * one — tall enough for a glyph with a word under it, short enough that it is
23
- * not competing with the page it is on. The ladder around it keeps the same
24
- * proportion to the glyph and the name it holds.
25
- */
26
- const rowMinHeightClasses = {
27
- xs: 'min-h-10',
28
- sm: 'min-h-12',
29
- md: 'min-h-14',
30
- lg: 'min-h-16',
31
- xl: 'min-h-18'
32
- };
33
- /** The air inside the sheet, around the row of items. */
34
- const rowPaddingClasses = {
35
- default: { xs: 'p-1', sm: 'p-1', md: 'p-1.5', lg: 'p-2', xl: 'p-2.5' },
36
- compact: { xs: 'p-0.5', sm: 'p-0.5', md: 'p-1', lg: 'p-1', xl: 'p-1.5' }
37
- };
38
- /** Between the glyph and the name under it. */
39
- const itemGapClasses = {
40
- xs: 'gap-0.5',
41
- sm: 'gap-0.5',
42
- md: 'gap-1',
43
- lg: 'gap-1',
44
- xl: 'gap-1.5'
45
- };
46
- /**
47
- * A row of destinations held against the bottom edge of the window.
48
- *
49
- * It is a `<nav>` rather than a `role="tablist"`, and its items are ordinary
50
- * links or buttons rather than tabs. That is a deliberate choice about what is
51
- * being promised: a tab list owes a keyboard reader one tab stop for the whole
52
- * set and arrow keys within it, and it owes a screen reader a panel per tab. A
53
- * bottom navigation switches what the *page* is, not which panel of one is
54
- * showing, and claiming the role without the behaviour is worse for a keyboard
55
- * reader than never claiming it. What is claimed instead is `aria-current`,
56
- * which is the honest statement: this is the destination you are on.
57
- *
58
- * The sheet is never dyed, exactly as on a `PlCard`. What carries the colour
59
- * family is the one item that is current.
60
- */
61
- export const PlBottomNavigation = /* @__PURE__ */ React.forwardRef(function PlBottomNavigation({ variant = 'glass', size = 'md', color = 'primary', density = 'default', elevation = 0, value: valueProp, defaultValue = null, onValueChange, position = 'fixed', labels = 'all', divider = true, safeArea = true, disabled = false, label, render, className, style, children, ...props }, ref) {
62
- const [uncontrolled, setUncontrolled] = React.useState(defaultValue);
63
- const controlled = valueProp !== undefined;
64
- const value = controlled ? valueProp : uncontrolled;
65
- const change = React.useCallback((next) => {
66
- if (!controlled) {
67
- setUncontrolled(next);
68
- }
69
- onValueChange?.(next);
70
- }, [controlled, onValueChange]);
71
- const context = React.useMemo(() => ({ value: value ?? null, change, size, density, labels, disabled }), [value, change, size, density, labels, disabled]);
72
- const classNames = cx('w-full min-w-0',
73
- // A bar spanning an edge of the window has nothing behind its corners, so
74
- // only one sitting in the flow is a sheet with corners at all.
75
- position === 'static' ? radiusClasses[size] : '', sheetRestClasses[variant],
76
- // A bar that is not in the flow has three edges against the window and one
77
- // against the content, so only that one is ever drawn — a hairline down
78
- // the left of the screen is a hairline nobody asked for. In the flow it is
79
- // an ordinary sheet and keeps the whole outline `sheetRestClasses` gave it.
80
- variant === 'glass' && position !== 'static' ? 'border-0' : '', divider ? sheetLineClasses : '', positionClasses[position],
81
- // The sheet keeps reaching the bottom of the screen; what the inset moves
82
- // is the row inside it. A bar that stopped above the home indicator would
83
- // leave a stripe of page showing under the glass.
84
- safeArea ? 'pb-[env(safe-area-inset-bottom)]' : '', transitionClasses, className);
85
- return useRender({
86
- render: render ?? _jsx("nav", {}),
87
- ref,
88
- props: {
89
- 'aria-label': label,
90
- className: classNames,
91
- style: { ...surfaceSlots(color, elevation), ...style },
92
- children: (_jsx(BottomNavigationContext.Provider, { value: context, children: _jsx("div", { className: cx('flex w-full items-stretch', rowMinHeightClasses[size], rowPaddingClasses[density][size]), children: children }) })),
93
- ...props
94
- }
95
- });
96
- });
97
- /**
98
- * One destination.
99
- *
100
- * It has no `size`, no `color` and no `variant` of its own: all three belong to
101
- * the bar, which is the only place they can be set once and mean the same thing
102
- * for every item.
103
- *
104
- * With an `href` it is a real `<a>`, which is what makes a long press offer
105
- * "open in a new tab" and what puts the destination in the status bar — neither
106
- * of which a `<button>` that calls `router.push` can do. Without one it is a
107
- * `<button>`, because a `<div>` carrying a click handler is invisible to a
108
- * keyboard.
109
- */
110
- export const PlBottomNavigationItem = /* @__PURE__ */ React.forwardRef(function PlBottomNavigationItem({ value, icon, href, disabled: disabledProp = false, className, children, onClick, ...props }, ref) {
111
- const bar = React.useContext(BottomNavigationContext);
112
- const disabled = disabledProp || bar.disabled;
113
- const selected = bar.value !== null && bar.value === value;
114
- const named = bar.labels === 'all' || (bar.labels === 'selected' && selected);
115
- const classNames = cx('flex min-w-0 flex-1 flex-col items-center justify-center px-1 py-1.5', itemGapClasses[bar.size], radiusClasses[bar.size], '[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]', transitionClasses,
116
- // Inset rather than offset: the item is inside a sheet that clips, and a
117
- // ring drawn outside it would have its top sliced off.
118
- focusRingInsetClasses,
119
- // An if/else rather than stacked variants: two Tailwind classes of equal
120
- // specificity resolve by their order in the generated stylesheet.
121
- disabled
122
- ? 'cursor-not-allowed opacity-50 saturate-[0.35] text-(--plass-muted-fg)'
123
- : selected
124
- ? 'cursor-pointer font-medium text-(--p-accent) bg-(--p-soft) hover:bg-(--p-soft-hover)'
125
- : 'cursor-pointer text-(--plass-muted-fg) hover:text-(--plass-fg) hover:bg-(--plass-glass-hover)', className);
126
- const body = (_jsxs(_Fragment, { children: [hasContent(icon) ? (_jsx("span", { className: cx('flex shrink-0 items-center justify-center', iconSizeClasses[bar.size]), children: icon })) : null, hasContent(children) ? (_jsx("span", { className: named
127
- ? cx('max-w-full truncate leading-tight', metaTextClasses[bar.size])
128
- : srOnlyClasses, children: children })) : null] }));
129
- const press = (event) => {
130
- if (disabled) {
131
- event.preventDefault();
132
- return;
133
- }
134
- bar.change(value);
135
- onClick?.(event);
136
- };
137
- if (href) {
138
- return (_jsx("a", { ref: ref, href: disabled ? undefined : href, "aria-current": selected ? 'page' : undefined, "aria-disabled": disabled || undefined, className: classNames, onClick: press, ...props, children: body }));
139
- }
140
- return (_jsx("button", { ref: ref, type: "button", disabled: disabled, "aria-current": selected ? 'page' : undefined, className: classNames, onClick: press, ...props, children: body }));
141
- });
1
+ "use client";import{jsx as e,Fragment as a,jsxs as t}from"react/jsx-runtime";import*as l from"react";import{useRender as s}from"@base-ui/react/use-render";import{cx as i,focusRingInsetClasses as n,hasContent as r,iconSizeClasses as o,metaTextClasses as c,radiusClasses as d,sheetLineClasses as m,sheetRestClasses as u,srOnlyClasses as p,surfaceSlots as f,transitionClasses as g}from"../../internal/styles.js";const h=/* @__PURE__ */l.createContext({value:null,change:()=>{},size:"md",density:"default",labels:"all",disabled:!1}),x={static:"",sticky:"sticky bottom-0 z-20",fixed:"fixed inset-x-0 bottom-0 z-30"},v={xs:"min-h-10",sm:"min-h-12",md:"min-h-14",lg:"min-h-16",xl:"min-h-18"},b={default:{xs:"p-1",sm:"p-1",md:"p-1.5",lg:"p-2",xl:"p-2.5"},compact:{xs:"p-0.5",sm:"p-0.5",md:"p-1",lg:"p-1",xl:"p-1.5"}},y={xs:"gap-0.5",sm:"gap-0.5",md:"gap-1",lg:"gap-1",xl:"gap-1.5"};export const PlBottomNavigation=/* @__PURE__ */l.forwardRef(function PlBottomNavigation({variant:a="glass",size:t="md",color:n="primary",density:r="default",elevation:o=0,value:c,defaultValue:p=null,onValueChange:y,position:N="fixed",labels:w="all",divider:z=!0,safeArea:k=!0,disabled:C=!1,label:j,render:P,className:B,style:I,children:R,...V},A){const[D,F]=l.useState(p),M=void 0!==c,S=M?c:D,q=l.useCallback(e=>{M||F(e),y?.(e)},[M,y]),E=l.useMemo(()=>({value:S??null,change:q,size:t,density:r,labels:w,disabled:C}),[S,q,t,r,w,C]),G=i("w-full min-w-0","static"===N?d[t]:"",u[a],"glass"===a&&"static"!==N?"border-0":"",z?m:"",x[N],k?"pb-[env(safe-area-inset-bottom)]":"",g,B);return s({render:P??e("nav",{}),ref:A,props:{"aria-label":j,className:G,style:{...f(n,o),...I},children:e(h.Provider,{value:E,children:e("div",{className:i("flex w-full items-stretch",v[t],b[r][t]),children:R})}),...V}})});export const PlBottomNavigationItem=/* @__PURE__ */l.forwardRef(function PlBottomNavigationItem({value:s,icon:m,href:u,disabled:f=!1,className:x,children:v,onClick:b,...N},w){const z=l.useContext(h),k=f||z.disabled,C=null!==z.value&&z.value===s,j="all"===z.labels||"selected"===z.labels&&C,P=i("flex min-w-0 flex-1 flex-col items-center justify-center px-1 py-1.5",y[z.size],d[z.size],"[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",g,n,k?"cursor-not-allowed opacity-50 saturate-[0.35] text-(--plass-muted-fg)":C?"cursor-pointer font-medium text-(--p-accent) bg-(--p-soft) hover:bg-(--p-soft-hover)":"cursor-pointer text-(--plass-muted-fg) hover:text-(--plass-fg) hover:bg-(--plass-glass-hover)",x),B=t(a,{children:[r(m)?e("span",{className:i("flex shrink-0 items-center justify-center",o[z.size]),children:m}):null,r(v)?e("span",{className:j?i("max-w-full truncate leading-tight",c[z.size]):p,children:v}):null]}),press=e=>{k?e.preventDefault():(z.change(s),b?.(e))};return u?e("a",{ref:w,href:k?void 0:u,"aria-current":C?"page":void 0,"aria-disabled":k||void 0,className:P,onClick:press,...N,children:B}):e("button",{ref:w,type:"button",disabled:k,"aria-current":C?"page":void 0,className:P,onClick:press,...N,children:B})});
@@ -1 +1 @@
1
- export { PlBottomNavigation, PlBottomNavigationItem } from './PlBottomNavigation.js';
1
+ export{PlBottomNavigation,PlBottomNavigationItem}from"./PlBottomNavigation.js";
@@ -1,46 +1 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import * as React from 'react';
3
- import { useRender } from '@base-ui/react/use-render';
4
- import { cx, radiusClasses, sheetPaddingXClasses, sheetPaddingYClasses, sheetRestClasses, surfaceSlots, transitionClasses } from '../../internal/styles.js';
5
- /**
6
- * A sheet of glass with content on it. The plainest surface in the library: it
7
- * groups things, and that is all it does.
8
- *
9
- * Everything structural — a title, a footer, hairlines between sections —
10
- * belongs to `PlCard`, which is a box with those sections laid out on it. What
11
- * is left here is the sheet itself, and the reason it is worth having on its own
12
- * is that most of what a screen groups has no heading: a well behind a form, a
13
- * tile in a shelf, a panel round a chart.
14
- *
15
- * `size` means something different here from what it means on a control, and
16
- * this is the one place in the library where that is true. A box is as tall as
17
- * what it holds, and its children bring their own typography — a container that
18
- * reset the type scale would render the same paragraph at two sizes depending
19
- * on what it was wrapped in. So `size` is the size of the **sheet**: its radius
20
- * and its padding, and nothing else.
21
- *
22
- * The three materials say what they say everywhere else, read as a container's:
23
- * the sheet is never dyed, because what a box holds arrives with its own
24
- * colours and tinting the pane under them puts every one on a background it was
25
- * not chosen against. The family reaches the hairline and the focus ring and
26
- * stops. `ghost` is the one to reach for inside another surface, where a second
27
- * bordered rectangle is a second rectangle.
28
- */
29
- export const PlBox = /* @__PURE__ */ React.forwardRef(function PlBox({ variant = 'glass', size = 'md', color = 'primary', density = 'default', elevation = 0, padded = true, render, className, style, children, ...props }, ref) {
30
- const classNames = cx('block', radiusClasses[size], padded ? `${sheetPaddingXClasses[density][size]} ${sheetPaddingYClasses[density][size]}` : '', sheetRestClasses[variant],
31
- // The same property list and duration as everything else, so a box whose
32
- // colour or elevation changes settles at the house pace. There is no
33
- // `:active` treatment because a box is not pressed — it holds things that
34
- // are.
35
- transitionClasses, className);
36
- return useRender({
37
- render: render ?? _jsx("div", {}),
38
- ref,
39
- props: {
40
- className: classNames,
41
- style: { ...surfaceSlots(color, elevation), ...style },
42
- children,
43
- ...props
44
- }
45
- });
46
- });
1
+ "use client";import{jsx as e}from"react/jsx-runtime";import*as r from"react";import{useRender as s}from"@base-ui/react/use-render";import{cx as t,radiusClasses as o,sheetPaddingXClasses as a,sheetPaddingYClasses as i,sheetRestClasses as n,surfaceSlots as l,transitionClasses as c}from"../../internal/styles.js";export const PlBox=/* @__PURE__ */r.forwardRef(function PlBox({variant:r="glass",size:d="md",color:m="primary",density:f="default",elevation:p=0,padded:u=!0,render:x,className:y,style:j,children:v,...b},h){const B=t("block",o[d],u?`${a[f][d]} ${i[f][d]}`:"",n[r],c,y);return s({render:x??e("div",{}),ref:h,props:{className:B,style:{...l(m,p),...j},children:v,...b}})});
@@ -1 +1 @@
1
- export { PlBox } from './PlBox.js';
1
+ export{PlBox}from"./PlBox.js";