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.
- package/dist/components/accordion/PlAccordion.js +1 -131
- package/dist/components/accordion/index.js +1 -1
- package/dist/components/alert/PlAlert.js +1 -109
- package/dist/components/alert/index.js +1 -1
- package/dist/components/animate-appear/PlAnimateAppear.js +1 -71
- package/dist/components/animate-appear/index.js +1 -1
- package/dist/components/animate-blink/PlAnimateBlink.js +1 -47
- package/dist/components/animate-blink/index.js +1 -1
- package/dist/components/animate-fade/PlAnimateFade.js +1 -48
- package/dist/components/animate-fade/index.js +1 -1
- package/dist/components/animate-grow/PlAnimateGrow.js +1 -49
- package/dist/components/animate-grow/index.js +1 -1
- package/dist/components/animate-headline/PlAnimateHeadline.js +1 -120
- package/dist/components/animate-headline/index.js +1 -1
- package/dist/components/animate-lighting/PlAnimateLighting.js +1 -65
- package/dist/components/animate-lighting/index.js +1 -1
- package/dist/components/animate-marquee/PlAnimateMarquee.js +1 -94
- package/dist/components/animate-marquee/index.js +1 -1
- package/dist/components/animate-rotate/PlAnimateRotate.js +1 -50
- package/dist/components/animate-rotate/index.js +1 -1
- package/dist/components/animate-slide/PlAnimateSlide.js +1 -49
- package/dist/components/animate-slide/index.js +1 -1
- package/dist/components/animate-typing/PlAnimateTyping.js +1 -177
- package/dist/components/animate-typing/index.js +1 -1
- package/dist/components/animate-zoom/PlAnimateZoom.js +1 -45
- package/dist/components/animate-zoom/index.js +1 -1
- package/dist/components/aspect-ratio/PlAspectRatio.js +1 -58
- package/dist/components/aspect-ratio/index.js +1 -1
- package/dist/components/avatar/PlAvatar.js +1 -121
- package/dist/components/avatar/index.js +1 -1
- package/dist/components/badge/PlBadge.js +1 -168
- package/dist/components/badge/index.js +1 -1
- package/dist/components/blockquote/PlBlockquote.js +1 -112
- package/dist/components/blockquote/index.js +1 -1
- package/dist/components/bottom-navigation/PlBottomNavigation.js +1 -141
- package/dist/components/bottom-navigation/index.js +1 -1
- package/dist/components/box/PlBox.js +1 -46
- package/dist/components/box/index.js +1 -1
- package/dist/components/breadcrumb/PlBreadcrumb.js +1 -201
- package/dist/components/breadcrumb/index.js +1 -1
- package/dist/components/button/PlButton.js +1 -196
- package/dist/components/button/index.js +1 -1
- package/dist/components/button-group/PlButtonGroup.js +1 -64
- package/dist/components/button-group/index.js +1 -1
- package/dist/components/card/PlCard.js +1 -102
- package/dist/components/card/index.js +1 -1
- package/dist/components/carousel/PlCarousel.js +1 -177
- package/dist/components/carousel/index.js +1 -1
- package/dist/components/chat-bubble/PlChatBubble.js +1 -206
- package/dist/components/chat-bubble/index.js +1 -1
- package/dist/components/checkbox/PlCheckbox.js +1 -100
- package/dist/components/checkbox/index.js +1 -1
- package/dist/components/chip/PlChip.js +1 -144
- package/dist/components/chip/index.js +1 -1
- package/dist/components/collapsible/PlCollapsible.js +1 -65
- package/dist/components/collapsible/index.js +1 -1
- package/dist/components/combobox/PlCombobox.js +1 -199
- package/dist/components/combobox/index.js +1 -1
- package/dist/components/container/PlContainer.js +1 -47
- package/dist/components/container/index.js +1 -1
- package/dist/components/date-picker/PlDatePicker.js +1 -87
- package/dist/components/date-picker/index.js +1 -1
- package/dist/components/date-range-picker/PlDateRangePicker.js +1 -152
- package/dist/components/date-range-picker/index.js +1 -1
- package/dist/components/date-time-picker/PlDateTimePicker.js +1 -106
- package/dist/components/date-time-picker/index.js +1 -1
- package/dist/components/divider/PlDivider.js +1 -107
- package/dist/components/divider/index.js +1 -1
- package/dist/components/drawer/PlDrawer.js +1 -190
- package/dist/components/drawer/index.js +1 -1
- package/dist/components/file-picker/PlFilePicker.js +1 -274
- package/dist/components/file-picker/index.js +1 -1
- package/dist/components/floating-bottom-navigation/PlFloatingBottomNavigation.js +1 -291
- package/dist/components/floating-bottom-navigation/index.js +1 -1
- package/dist/components/grid/PlGrid.js +1 -51
- package/dist/components/grid/PlGridItem.js +1 -34
- package/dist/components/grid/index.js +1 -2
- package/dist/components/highlight/PlHighlight.js +1 -185
- package/dist/components/highlight/index.js +1 -1
- package/dist/components/hot-keys/PlHotKeys.js +1 -294
- package/dist/components/hot-keys/index.js +1 -1
- package/dist/components/icon/PlIcon.js +1 -58
- package/dist/components/icon/index.js +1 -1
- package/dist/components/icon-button/PlIconButton.js +1 -37
- package/dist/components/icon-button/index.js +1 -1
- package/dist/components/list/PlList.js +1 -160
- package/dist/components/list/index.js +1 -1
- package/dist/components/menu/PlMenu.js +1 -209
- package/dist/components/menu/index.js +1 -1
- package/dist/components/modal/PlModal.js +1 -150
- package/dist/components/modal/index.js +1 -1
- package/dist/components/number-field/PlNumberField.js +1 -111
- package/dist/components/number-field/index.js +1 -1
- package/dist/components/otp-field/PlOtpField.js +1 -109
- package/dist/components/otp-field/index.js +1 -1
- package/dist/components/overlay/PlOverlay.js +1 -77
- package/dist/components/overlay/index.js +1 -1
- package/dist/components/pagination/PlPagination.js +1 -159
- package/dist/components/pagination/index.js +1 -1
- package/dist/components/panes/PlPanes.js +1 -324
- package/dist/components/panes/index.js +1 -1
- package/dist/components/pill/PlPill.js +1 -154
- package/dist/components/pill/index.js +1 -1
- package/dist/components/popover/PlPopover.js +1 -113
- package/dist/components/popover/index.js +1 -1
- package/dist/components/progress-box/PlProgressBox.js +1 -34
- package/dist/components/progress-box/index.js +1 -1
- package/dist/components/progress-circular/PlProgressCircular.js +1 -47
- package/dist/components/progress-circular/index.js +1 -1
- package/dist/components/progress-linear/PlProgressLinear.js +1 -40
- package/dist/components/progress-linear/index.js +1 -1
- package/dist/components/radio-group/PlRadioGroup.js +1 -99
- package/dist/components/radio-group/index.js +1 -1
- package/dist/components/rating/PlRating.js +1 -101
- package/dist/components/rating/index.js +1 -1
- package/dist/components/scroll-zone/PlScrollZone.js +1 -411
- package/dist/components/scroll-zone/index.js +1 -1
- package/dist/components/segmented-button/PlSegmentedButton.js +1 -206
- package/dist/components/segmented-button/index.js +1 -1
- package/dist/components/select/PlSelect.js +1 -115
- package/dist/components/select/index.js +1 -1
- package/dist/components/skeleton/PlSkeleton.js +1 -142
- package/dist/components/skeleton/index.js +1 -1
- package/dist/components/slider/PlSlider.js +1 -132
- package/dist/components/slider/index.js +1 -1
- package/dist/components/spoiler/PlSpoiler.js +1 -74
- package/dist/components/spoiler/index.js +1 -1
- package/dist/components/switch/PlSwitch.js +1 -131
- package/dist/components/switch/index.js +1 -1
- package/dist/components/table/PlTable.js +1 -210
- package/dist/components/table/index.js +1 -1
- package/dist/components/tabs/PlTabs.js +1 -182
- package/dist/components/tabs/index.js +1 -1
- package/dist/components/text-field/PlTextField.js +1 -126
- package/dist/components/text-field/index.js +1 -1
- package/dist/components/text-link/PlTextLink.js +1 -136
- package/dist/components/text-link/index.js +1 -1
- package/dist/components/time-picker/PlTimePicker.js +1 -97
- package/dist/components/time-picker/index.js +1 -1
- package/dist/components/timeline/PlTimeline.js +1 -207
- package/dist/components/timeline/index.js +1 -1
- package/dist/components/toast/PlToast.js +1 -174
- package/dist/components/toast/index.js +1 -1
- package/dist/components/toolbar/PlToolbar.js +1 -65
- package/dist/components/toolbar/index.js +1 -1
- package/dist/components/tooltip/PlTooltip.js +1 -117
- package/dist/components/tooltip/index.js +1 -1
- package/dist/components/typography/PlTypography.js +1 -143
- package/dist/components/typography/index.js +1 -1
- package/dist/index.js +1 -75
- package/dist/internal/animate.js +1 -318
- package/dist/internal/button-group.js +2 -19
- package/dist/internal/calendar.js +1 -501
- package/dist/internal/date.js +1 -353
- package/dist/internal/format.js +1 -41
- package/dist/internal/grid.js +1 -143
- package/dist/internal/icons.js +1 -138
- package/dist/internal/menu.js +1 -18
- package/dist/internal/picker.js +1 -139
- package/dist/internal/progress.js +1 -167
- package/dist/internal/sizer.js +1 -35
- package/dist/internal/styles.js +1 -636
- package/dist/types.js +0 -8
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export{PlIcon}from"./PlIcon.js";
|
|
@@ -1,37 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import { PlButton } from '../button/PlButton.js';
|
|
4
|
-
/**
|
|
5
|
-
* A round button with a glyph in it and nothing else.
|
|
6
|
-
*
|
|
7
|
-
* A `PlButton` with an icon and no children already goes square — the same
|
|
8
|
-
* height, the same width, the house fillet cut off it. This is the other shape:
|
|
9
|
-
* a disc.
|
|
10
|
-
*
|
|
11
|
-
* That disc is a deliberate exception to the radius rule, which holds every
|
|
12
|
-
* corner well short of the 50% that would make a control a pill, because the
|
|
13
|
-
* flat run along the top and bottom edge is what still reads as a sheet with its
|
|
14
|
-
* corners cut. The rule is about *labelled* controls: the flat run is there for
|
|
15
|
-
* the line of text to sit on, and a glyph has no line of text. A circle with a
|
|
16
|
-
* single mark centred in it is a punched token rather than a moulded key, so it
|
|
17
|
-
* says the thing the rule exists to protect by a different route.
|
|
18
|
-
*
|
|
19
|
-
* Everything else is `PlButton`'s, unchanged and on purpose: the three
|
|
20
|
-
* materials, the elevation ladder, the pointer light, `loading`, `readOnly` and
|
|
21
|
-
* `disabled`. Two components that draw the same surface out of two copies of the
|
|
22
|
-
* same table are two components that will eventually disagree.
|
|
23
|
-
*/
|
|
24
|
-
export const PlIconButton = /* @__PURE__ */ React.forwardRef(function PlIconButton({ icon, label, style, ...props }, ref) {
|
|
25
|
-
return (_jsx(PlButton, { ref: ref, "aria-label": label,
|
|
26
|
-
// The icon goes in `startIcon` rather than in `children`, which is what
|
|
27
|
-
// puts PlButton on its icon-only path: square footprint, no horizontal
|
|
28
|
-
// padding, and the spinner taking the glyph's place while `loading`.
|
|
29
|
-
startIcon: icon,
|
|
30
|
-
// An inline style rather than a `rounded-full`, and for once not as a
|
|
31
|
-
// shortcut. PlButton already writes a `rounded-*` utility of its own, and
|
|
32
|
-
// two utilities setting the same property resolve by their order in the
|
|
33
|
-
// generated stylesheet — which is not something a component may depend
|
|
34
|
-
// on. An inline declaration is the one form that wins deterministically,
|
|
35
|
-
// and it still leaves the caller's own `style` free to override it below.
|
|
36
|
-
style: { borderRadius: '9999px', ...style }, ...props }));
|
|
37
|
-
});
|
|
1
|
+
"use client";import{jsx as t}from"react/jsx-runtime";import*as o from"react";import{PlButton as r}from"../button/PlButton.js";export const PlIconButton=/* @__PURE__ */o.forwardRef(function PlIconButton({icon:o,label:e,style:n,...a},s){return t(r,{ref:s,"aria-label":e,startIcon:o,style:{borderRadius:"9999px",...n},...a})});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export{PlIconButton}from"./PlIconButton.js";
|
|
@@ -1,160 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import { useRender } from '@base-ui/react/use-render';
|
|
4
|
-
import { focusRingClasses, gapClasses, glassClasses, hasContent, iconClasses, metaTextClasses, paddingXClasses, radiusClasses, sheetBodyClasses, surfaceSlots, transitionClasses } from '../../internal/styles.js';
|
|
5
|
-
const ListContext = /* @__PURE__ */ React.createContext({
|
|
6
|
-
size: 'md',
|
|
7
|
-
density: 'default',
|
|
8
|
-
dividers: false
|
|
9
|
-
});
|
|
10
|
-
/**
|
|
11
|
-
* The three materials, said the way a *container* says them — the sheet is never
|
|
12
|
-
* dyed, exactly as on a `PlCard`. A list holds other people's content, and that
|
|
13
|
-
* content arrives with its own colours.
|
|
14
|
-
*
|
|
15
|
-
* `ghost` is the one to reach for inside a card: the card is already a sheet,
|
|
16
|
-
* and a second bordered rectangle inside it is a second rectangle.
|
|
17
|
-
*/
|
|
18
|
-
const variantClasses = {
|
|
19
|
-
solid: /* @__PURE__ */ [
|
|
20
|
-
glassClasses,
|
|
21
|
-
'text-(--plass-fg) bg-(--plass-glass-press)',
|
|
22
|
-
'[box-shadow:var(--p-elev),var(--plass-gloss-glass)]'
|
|
23
|
-
].join(' '),
|
|
24
|
-
glass: /* @__PURE__ */ [
|
|
25
|
-
glassClasses,
|
|
26
|
-
'border text-(--plass-fg) bg-(--plass-glass)',
|
|
27
|
-
'[border-color:var(--plass-glass-line)]',
|
|
28
|
-
'[box-shadow:var(--p-elev),var(--plass-gloss-glass)]'
|
|
29
|
-
].join(' '),
|
|
30
|
-
ghost: 'text-(--plass-fg) bg-transparent'
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
|
-
* A row's vertical padding. Its own ladder rather than a sheet's, because a row
|
|
34
|
-
* is a line of text in a stack of them and a sheet is a container: the same `md`
|
|
35
|
-
* that gives a card 20px of air would give a list of eight rows the height of a
|
|
36
|
-
* page.
|
|
37
|
-
*/
|
|
38
|
-
const rowPaddingYClasses = {
|
|
39
|
-
default: { xs: 'py-1', sm: 'py-1.5', md: 'py-2', lg: 'py-2.5', xl: 'py-3' },
|
|
40
|
-
compact: { xs: 'py-0.5', sm: 'py-0.5', md: 'py-1', lg: 'py-1.5', xl: 'py-2' }
|
|
41
|
-
};
|
|
42
|
-
/**
|
|
43
|
-
* A row's horizontal padding: a control's, not a sheet's. The words in a row are
|
|
44
|
-
* a label on a line rather than a paragraph inside a container, and a sheet's
|
|
45
|
-
* inset would push every row's text a third of the way across a narrow list.
|
|
46
|
-
*/
|
|
47
|
-
const rowPaddingXClasses = paddingXClasses;
|
|
48
|
-
/**
|
|
49
|
-
* A row sits one step down the radius ladder from the sheet it is inside — a
|
|
50
|
-
* tile cut out of a sheet cannot have the same corner as the sheet, or the two
|
|
51
|
-
* curves fight along the edge.
|
|
52
|
-
*/
|
|
53
|
-
const rowRadiusClasses = {
|
|
54
|
-
xs: radiusClasses.xs,
|
|
55
|
-
sm: radiusClasses.xs,
|
|
56
|
-
md: radiusClasses.sm,
|
|
57
|
-
lg: radiusClasses.sm,
|
|
58
|
-
xl: radiusClasses.md
|
|
59
|
-
};
|
|
60
|
-
/**
|
|
61
|
-
* The rule between two rows, and the rule that makes the sheet give up its
|
|
62
|
-
* padding: `>li+li` rather than a class on each item, so it holds however the
|
|
63
|
-
* caller composed the rows — through a `.map()`, through fragments, through a
|
|
64
|
-
* component of their own that renders a `PlListItem`.
|
|
65
|
-
*
|
|
66
|
-
* `--plass-divider` and not the sheet's white hairline, for the reason a
|
|
67
|
-
* checkbox's edge takes a neutral one: white light on a translucent pane is
|
|
68
|
-
* invisible the moment the list is set on something opaque. It is the same ink
|
|
69
|
-
* a PlCard is scored with and a PlTable rules its rows in, so a list on a card
|
|
70
|
-
* inside a table cell is one family of lines rather than three.
|
|
71
|
-
*/
|
|
72
|
-
const dividerClasses = '[&>li+li]:border-t [&>li+li]:[border-color:var(--plass-divider)]';
|
|
73
|
-
/**
|
|
74
|
-
* A stack of rows.
|
|
75
|
-
*
|
|
76
|
-
* The list is a sheet and the rows are what is on it, which is the whole reason
|
|
77
|
-
* the two are separate components: `size` and `density` are properties of the
|
|
78
|
-
* stack, not of any one line in it, and a context is what carries them down.
|
|
79
|
-
*
|
|
80
|
-
* There is no Base UI primitive under this on purpose. A list is not a composite
|
|
81
|
-
* widget — it has no roving focus, no selection model, no keyboard contract of
|
|
82
|
-
* its own. Reaching for a menu or a listbox primitive to get one would hand
|
|
83
|
-
* every consumer's plain list of links the semantics of a menu, which is the
|
|
84
|
-
* most common way a component library breaks a screen reader.
|
|
85
|
-
*/
|
|
86
|
-
export const PlList = /* @__PURE__ */ React.forwardRef(function PlList({ variant = 'glass', size = 'md', color = 'primary', density = 'default', elevation = 0, dividers = false, render, className, style, children, ...props }, ref) {
|
|
87
|
-
const context = React.useMemo(() => ({ size, density, dividers }), [size, density, dividers]);
|
|
88
|
-
const classNames = [
|
|
89
|
-
'flex flex-col',
|
|
90
|
-
radiusClasses[size],
|
|
91
|
-
variantClasses[variant],
|
|
92
|
-
transitionClasses,
|
|
93
|
-
// Without dividers the rows are tiles and the sheet keeps a hair of padding
|
|
94
|
-
// so a hovered row does not run into the edge. With them the rules have to
|
|
95
|
-
// reach the edge, so the padding goes and the rows square off.
|
|
96
|
-
dividers ? `overflow-hidden ${dividerClasses}` : 'p-1',
|
|
97
|
-
className ?? ''
|
|
98
|
-
]
|
|
99
|
-
.filter(Boolean)
|
|
100
|
-
.join(' ');
|
|
101
|
-
const element = useRender({
|
|
102
|
-
render,
|
|
103
|
-
ref,
|
|
104
|
-
props: {
|
|
105
|
-
// Tailwind's reset takes the bullets off every `<ul>`, and Safari takes
|
|
106
|
-
// the list semantics off with them. Saying `role="list"` out loud is the
|
|
107
|
-
// one-line fix, and it costs nothing when the reset is not there.
|
|
108
|
-
role: 'list',
|
|
109
|
-
className: classNames,
|
|
110
|
-
style: { ...surfaceSlots(color, elevation), ...style },
|
|
111
|
-
children,
|
|
112
|
-
...props
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
return _jsx(ListContext.Provider, { value: context, children: element });
|
|
116
|
-
});
|
|
117
|
-
/**
|
|
118
|
-
* One row.
|
|
119
|
-
*
|
|
120
|
-
* The shell is always an `<li>`. What changes is what is inside it: a plain run
|
|
121
|
-
* of content, or — when `onClick` or `href` is given — a real `<button>` or
|
|
122
|
-
* `<a>` wrapping that content, with `action` sitting outside it as a separate
|
|
123
|
-
* control. This is the same shape a `PlChip` uses, for the same two reasons: a
|
|
124
|
-
* `<span>` carrying a click handler is invisible to a keyboard, and a
|
|
125
|
-
* `<button>` inside a `<button>` is markup the browser silently un-nests.
|
|
126
|
-
*/
|
|
127
|
-
export const PlListItem = /* @__PURE__ */ React.forwardRef(function PlListItem({ startIcon, endIcon, description, action, href, selected = false, disabled = false, className, children, onClick, ...props }, ref) {
|
|
128
|
-
const { size, density, dividers } = React.useContext(ListContext);
|
|
129
|
-
const interactive = Boolean(onClick || href) && !disabled;
|
|
130
|
-
const padX = rowPaddingXClasses[density][size];
|
|
131
|
-
const padY = rowPaddingYClasses[density][size];
|
|
132
|
-
const bodyClassNames = [
|
|
133
|
-
'flex min-w-0 flex-1 items-center text-start',
|
|
134
|
-
padX,
|
|
135
|
-
padY,
|
|
136
|
-
gapClasses[size],
|
|
137
|
-
sheetBodyClasses[size],
|
|
138
|
-
transitionClasses,
|
|
139
|
-
iconClasses,
|
|
140
|
-
// Squared off when the rows are ruled, for the reason `dividerClasses`
|
|
141
|
-
// exists: a tile and a line are two different ideas about what a row is.
|
|
142
|
-
dividers ? '' : rowRadiusClasses[size],
|
|
143
|
-
// An if/else rather than stacked variants: two Tailwind classes of equal
|
|
144
|
-
// specificity resolve by their order in the generated stylesheet.
|
|
145
|
-
disabled
|
|
146
|
-
? 'cursor-not-allowed opacity-50 saturate-[0.35]'
|
|
147
|
-
: selected
|
|
148
|
-
? 'bg-(--p-soft-press) font-medium text-(--p-accent)'
|
|
149
|
-
: '',
|
|
150
|
-
interactive ? `cursor-pointer ${focusRingClasses}` : '',
|
|
151
|
-
// Hover deepens the same tint `selected` already uses, one step down, so a
|
|
152
|
-
// hovered row and the chosen row are the same idea at two strengths.
|
|
153
|
-
interactive && !selected ? 'hover:bg-(--p-soft)' : '',
|
|
154
|
-
interactive && selected ? 'hover:bg-(--p-soft-press)' : ''
|
|
155
|
-
]
|
|
156
|
-
.filter(Boolean)
|
|
157
|
-
.join(' ');
|
|
158
|
-
const body = (_jsxs(_Fragment, { children: [hasContent(startIcon) ? (_jsx("span", { className: "flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)", children: startIcon })) : null, _jsxs("span", { className: "flex min-w-0 flex-1 flex-col", children: [hasContent(children) ? _jsx("span", { className: "truncate", children: children }) : null, hasContent(description) ? (_jsx("span", { className: `truncate text-(--plass-muted-fg) ${metaTextClasses[size]}`, children: description })) : null] }), hasContent(endIcon) ? (_jsx("span", { className: "flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)", children: endIcon })) : null] }));
|
|
159
|
-
return (_jsxs("li", { ref: ref, className: ['flex w-full items-center', className ?? ''].filter(Boolean).join(' '), ...props, children: [interactive && href ? (_jsx("a", { href: href, className: bodyClassNames, "aria-current": selected ? 'page' : undefined, onClick: onClick, children: body })) : interactive ? (_jsx("button", { type: "button", className: bodyClassNames, "aria-current": selected ? true : undefined, onClick: onClick, children: body })) : (_jsx("div", { className: bodyClassNames, "aria-disabled": disabled || undefined, children: body })), hasContent(action) ? (_jsx("div", { className: `flex shrink-0 items-center ${padX}`, children: action })) : null] }));
|
|
160
|
-
});
|
|
1
|
+
"use client";import{jsx as e,jsxs as s,Fragment as l}from"react/jsx-runtime";import*as r from"react";import{useRender as t}from"@base-ui/react/use-render";import{focusRingClasses as a,gapClasses as i,glassClasses as n,hasContent as o,iconClasses as d,metaTextClasses as c,paddingXClasses as p,radiusClasses as m,sheetBodyClasses as f,surfaceSlots as x,transitionClasses as u}from"../../internal/styles.js";const h=/* @__PURE__ */r.createContext({size:"md",density:"default",dividers:!1}),g={solid:/* @__PURE__ */[n,"text-(--plass-fg) bg-(--plass-glass-press)","[box-shadow:var(--p-elev),var(--plass-gloss-glass)]"].join(" "),glass:/* @__PURE__ */[n,"border text-(--plass-fg) bg-(--plass-glass)","[border-color:var(--plass-glass-line)]","[box-shadow:var(--p-elev),var(--plass-gloss-glass)]"].join(" "),ghost:"text-(--plass-fg) bg-transparent"},v={default:{xs:"py-1",sm:"py-1.5",md:"py-2",lg:"py-2.5",xl:"py-3"},compact:{xs:"py-0.5",sm:"py-0.5",md:"py-1",lg:"py-1.5",xl:"py-2"}},y=p,b={xs:m.xs,sm:m.xs,md:m.sm,lg:m.sm,xl:m.md};export const PlList=/* @__PURE__ */r.forwardRef(function PlList({variant:s="glass",size:l="md",color:a="primary",density:i="default",elevation:n=0,dividers:o=!1,render:d,className:c,style:p,children:f,...v},y){const b=r.useMemo(()=>({size:l,density:i,dividers:o}),[l,i,o]),N=["flex flex-col",m[l],g[s],u,o?"overflow-hidden [&>li+li]:border-t [&>li+li]:[border-color:var(--plass-divider)]":"p-1",c??""].filter(Boolean).join(" "),j=t({render:d,ref:y,props:{role:"list",className:N,style:{...x(a,n),...p},children:f,...v}});return e(h.Provider,{value:b,children:j})});export const PlListItem=/* @__PURE__ */r.forwardRef(function PlListItem({startIcon:t,endIcon:n,description:p,action:m,href:x,selected:g=!1,disabled:N=!1,className:j,children:w,onClick:k,...C},P){const{size:z,density:B,dividers:I}=r.useContext(h),L=Boolean(k||x)&&!N,$=y[B][z],R=["flex min-w-0 flex-1 items-center text-start",$,v[B][z],i[z],f[z],u,d,I?"":b[z],N?"cursor-not-allowed opacity-50 saturate-[0.35]":g?"bg-(--p-soft-press) font-medium text-(--p-accent)":"",L?`cursor-pointer ${a}`:"",L&&!g?"hover:bg-(--p-soft)":"",L&&g?"hover:bg-(--p-soft-press)":""].filter(Boolean).join(" "),F=s(l,{children:[o(t)?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)",children:t}):null,s("span",{className:"flex min-w-0 flex-1 flex-col",children:[o(w)?e("span",{className:"truncate",children:w}):null,o(p)?e("span",{className:`truncate text-(--plass-muted-fg) ${c[z]}`,children:p}):null]}),o(n)?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)",children:n}):null]});return s("li",{ref:P,className:["flex w-full items-center",j??""].filter(Boolean).join(" "),...C,children:[L&&x?e("a",{href:x,className:R,"aria-current":g?"page":void 0,onClick:k,children:F}):L?e("button",{type:"button",className:R,"aria-current":!!g||void 0,onClick:k,children:F}):e("div",{className:R,"aria-disabled":N||void 0,children:F}),o(m)?e("div",{className:`flex shrink-0 items-center ${$}`,children:m}):null]})});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export{PlList,PlListItem}from"./PlList.js";
|
|
@@ -1,209 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import { Menu as BaseUIMenu } from '@base-ui/react/menu';
|
|
4
|
-
import { ContextMenu as BaseUIContextMenu } from '@base-ui/react/context-menu';
|
|
5
|
-
import { MenuContext } from '../../internal/menu.js';
|
|
6
|
-
import { CheckIcon, ChevronIcon, DotIcon } from '../../internal/icons.js';
|
|
7
|
-
import { controlTextLeadingClasses, cx, gapClasses, glassClasses, hasContent, iconClasses, metaTextClasses, radiusClasses, surfaceSlots, transitionClasses } from '../../internal/styles.js';
|
|
8
|
-
/* ---------------------------------------------------------------------------
|
|
9
|
-
* The surface
|
|
10
|
-
* ------------------------------------------------------------------------- */
|
|
11
|
-
/**
|
|
12
|
-
* The popup, which is `PlSelect`'s popup to the pixel — deliberately, because a
|
|
13
|
-
* select *is* a menu that remembers what you picked, and two floating lists of
|
|
14
|
-
* rows that do not match are two lists the eye has to learn separately.
|
|
15
|
-
*/
|
|
16
|
-
const popupClasses = /* @__PURE__ */ [
|
|
17
|
-
glassClasses,
|
|
18
|
-
'max-h-[min(24rem,var(--available-height))] min-w-40 overflow-y-auto overscroll-contain',
|
|
19
|
-
'border bg-(--plass-glass-press) p-1',
|
|
20
|
-
'[border-color:var(--plass-glass-line)]',
|
|
21
|
-
'[box-shadow:var(--plass-shadow-3),var(--plass-gloss-glass)]',
|
|
22
|
-
'[outline:none]',
|
|
23
|
-
// Opacity only. A menu that slides in has moved the row you were already
|
|
24
|
-
// reaching for, which is the one thing a menu must never do.
|
|
25
|
-
'[transition:opacity_var(--plass-duration)_var(--plass-ease)]',
|
|
26
|
-
'data-[starting-style]:opacity-0 data-[ending-style]:opacity-0'
|
|
27
|
-
].join(' ');
|
|
28
|
-
/**
|
|
29
|
-
* A row's padding, and a ladder of its own rather than the sheet track.
|
|
30
|
-
*
|
|
31
|
-
* A `PlList` row spans a sheet that something else decided the width of; a menu
|
|
32
|
-
* row is inside a popup that is exactly as wide as its longest label. The sheet
|
|
33
|
-
* track's `px-5` at `md` would add 40px to a menu that says "Cut", which is how
|
|
34
|
-
* a five-row menu ends up the width of a dialog.
|
|
35
|
-
*/
|
|
36
|
-
const rowPaddingClasses = {
|
|
37
|
-
default: {
|
|
38
|
-
xs: 'px-1.5 py-0.5',
|
|
39
|
-
sm: 'px-2 py-1',
|
|
40
|
-
md: 'px-2.5 py-1.5',
|
|
41
|
-
lg: 'px-3 py-2',
|
|
42
|
-
xl: 'px-3.5 py-2.5'
|
|
43
|
-
},
|
|
44
|
-
compact: {
|
|
45
|
-
xs: 'px-1 py-0.5',
|
|
46
|
-
sm: 'px-1.5 py-0.5',
|
|
47
|
-
md: 'px-2 py-1',
|
|
48
|
-
lg: 'px-2.5 py-1',
|
|
49
|
-
xl: 'px-3 py-1.5'
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
/**
|
|
53
|
-
* A row sits one step down the radius ladder from the popup it is inside: a
|
|
54
|
-
* tile cut out of a sheet cannot carry the sheet's own corner, or the two curves
|
|
55
|
-
* fight along the edge.
|
|
56
|
-
*/
|
|
57
|
-
const rowRadiusClasses = {
|
|
58
|
-
xs: radiusClasses.xs,
|
|
59
|
-
sm: radiusClasses.xs,
|
|
60
|
-
md: radiusClasses.sm,
|
|
61
|
-
lg: radiusClasses.sm,
|
|
62
|
-
xl: radiusClasses.md
|
|
63
|
-
};
|
|
64
|
-
/**
|
|
65
|
-
* The row, in every one of its shapes — plain, link, submenu trigger, checkbox,
|
|
66
|
-
* radio. They differ in which Base UI part renders them and in nothing else.
|
|
67
|
-
*
|
|
68
|
-
* `data-highlighted` rather than `:hover`, exactly as on a `PlSelect` option: it
|
|
69
|
-
* is also what the arrow keys move, so the mouse and the keyboard light the same
|
|
70
|
-
* row instead of the keyboard lighting nothing.
|
|
71
|
-
*
|
|
72
|
-
* `accented` is a parameter rather than a class the caller appends, and that is
|
|
73
|
-
* not a style preference. Appending `text-(--p-accent)` next to the default
|
|
74
|
-
* `text-(--plass-fg)` puts two utilities of equal specificity on one element,
|
|
75
|
-
* and which of them wins is decided by their order in the generated stylesheet
|
|
76
|
-
* rather than by the order they were written in — so `color="danger"` on a row
|
|
77
|
-
* would silently do nothing. Branching here is what makes only one of the two
|
|
78
|
-
* exist.
|
|
79
|
-
*/
|
|
80
|
-
function rowClasses(size, density, accented, className) {
|
|
81
|
-
return cx('relative flex w-full cursor-pointer items-center select-none', accented ? 'text-(--p-accent)' : 'text-(--plass-fg)', rowPaddingClasses[density][size], rowRadiusClasses[size], gapClasses[size], controlTextLeadingClasses[size], transitionClasses, iconClasses, 'data-[highlighted]:bg-(--p-soft-hover)', 'data-[popup-open]:bg-(--p-soft)', 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50',
|
|
82
|
-
// Base UI moves focus onto the highlighted row itself, so a ring here would
|
|
83
|
-
// draw a rectangle inside the popup on every arrow press. The tint is the
|
|
84
|
-
// focus indicator, which is what makes it the same one the mouse gets.
|
|
85
|
-
'[outline:none]', className);
|
|
86
|
-
}
|
|
87
|
-
/** The fixed-width slot a check, a dot or a `startIcon` lands in. */
|
|
88
|
-
const slotClasses = 'flex h-[1lh] w-[1.2em] shrink-0 items-center justify-center';
|
|
89
|
-
/** The muted run of text a shortcut is set in, at the end of the row. */
|
|
90
|
-
function shortcutClasses(size) {
|
|
91
|
-
return cx('ms-2 shrink-0 text-(--plass-muted-fg) tabular-nums', metaTextClasses[size]);
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* The label, and the description under it when there is one.
|
|
95
|
-
*
|
|
96
|
-
* `min-w-0` so a long label truncates rather than pushing the shortcut off the
|
|
97
|
-
* end of a popup that has already been positioned.
|
|
98
|
-
*/
|
|
99
|
-
function RowBody({ children, description, size }) {
|
|
100
|
-
if (!hasContent(description)) {
|
|
101
|
-
return _jsx("span", { className: "min-w-0 flex-1 truncate text-start", children: children });
|
|
102
|
-
}
|
|
103
|
-
return (_jsxs("span", { className: "flex min-w-0 flex-1 flex-col text-start", children: [_jsx("span", { className: "truncate", children: children }), _jsx("span", { className: cx('truncate text-(--plass-muted-fg)', metaTextClasses[size]), children: description })] }));
|
|
104
|
-
}
|
|
105
|
-
/* ---------------------------------------------------------------------------
|
|
106
|
-
* The parts
|
|
107
|
-
* ------------------------------------------------------------------------- */
|
|
108
|
-
/**
|
|
109
|
-
* One row of a menu.
|
|
110
|
-
*
|
|
111
|
-
* Renders a real `<a>` when it is given an `href` and Base UI's own item
|
|
112
|
-
* otherwise — the same split `PlListItem` makes, for the same reason. A menu of
|
|
113
|
-
* links that are not links cannot be opened in a new tab, cannot be copied, and
|
|
114
|
-
* tells a screen reader the wrong thing about every one of them.
|
|
115
|
-
*/
|
|
116
|
-
export function PlMenuItem({ onClick, href, target, startIcon, endIcon, shortcut, description, color, closeOnClick = true, disabled = false, label, children, className, style }) {
|
|
117
|
-
const { size, density } = React.useContext(MenuContext);
|
|
118
|
-
const body = (_jsxs(_Fragment, { children: [hasContent(startIcon) ? (_jsx("span", { className: cx(slotClasses, 'text-(--plass-muted-fg)'), children: startIcon })) : null, _jsx(RowBody, { description: description, size: size, children: children }), hasContent(endIcon) ? (_jsx("span", { className: cx(slotClasses, 'text-(--plass-muted-fg)'), children: endIcon })) : null, hasContent(shortcut) ? _jsx("span", { className: shortcutClasses(size), children: shortcut }) : null] }));
|
|
119
|
-
// A row can name its own family — `color="danger"` on the one that deletes —
|
|
120
|
-
// and the slots are re-declared on the row so the tint, the hairline and the
|
|
121
|
-
// text all turn over together rather than one of them staying indigo.
|
|
122
|
-
const slots = color ? surfaceSlots(color, 0) : undefined;
|
|
123
|
-
const rowStyle = slots || style ? { ...slots, ...style } : undefined;
|
|
124
|
-
if (href !== undefined) {
|
|
125
|
-
return (_jsx(BaseUIMenu.LinkItem, { href: href, target: target, label: label, closeOnClick: closeOnClick, onClick: onClick, className: rowClasses(size, density, Boolean(color), className), style: rowStyle, children: body }));
|
|
126
|
-
}
|
|
127
|
-
return (_jsx(BaseUIMenu.Item, { disabled: disabled, label: label, closeOnClick: closeOnClick, onClick: onClick, className: rowClasses(size, density, Boolean(color), className), style: rowStyle, children: body }));
|
|
128
|
-
}
|
|
129
|
-
/** A row that ticks. The tick lands in the same slot a `startIcon` would. */
|
|
130
|
-
export function PlMenuCheckboxItem({ checked, defaultChecked, onCheckedChange, endIcon, shortcut, description, color, closeOnClick = false, disabled = false, label, children, className, style }) {
|
|
131
|
-
const { size, density } = React.useContext(MenuContext);
|
|
132
|
-
const slots = color ? surfaceSlots(color, 0) : undefined;
|
|
133
|
-
return (_jsxs(BaseUIMenu.CheckboxItem, { checked: checked, defaultChecked: defaultChecked, onCheckedChange: (next) => onCheckedChange?.(next), disabled: disabled, label: label, closeOnClick: closeOnClick, className: rowClasses(size, density, Boolean(color), className), style: slots || style ? { ...slots, ...style } : undefined, children: [_jsx("span", { className: cx(slotClasses, 'text-(--p-accent)'), children: _jsx(BaseUIMenu.CheckboxItemIndicator, { className: "flex items-center justify-center", children: _jsx(CheckIcon, {}) }) }), _jsx(RowBody, { description: description, size: size, children: children }), hasContent(endIcon) ? (_jsx("span", { className: cx(slotClasses, 'text-(--plass-muted-fg)'), children: endIcon })) : null, hasContent(shortcut) ? _jsx("span", { className: shortcutClasses(size), children: shortcut }) : null] }));
|
|
134
|
-
}
|
|
135
|
-
/** One choice out of a set. Wraps the rows that make up the set. */
|
|
136
|
-
export function PlMenuRadioGroup({ value, defaultValue, onValueChange, disabled = false, children, className }) {
|
|
137
|
-
return (_jsx(BaseUIMenu.RadioGroup, { value: value, defaultValue: defaultValue, onValueChange: (next) => onValueChange?.(next), disabled: disabled, className: className, children: children }));
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* A row inside a `PlMenuRadioGroup`.
|
|
141
|
-
*
|
|
142
|
-
* Marked with a dot rather than a tick, which is the same distinction
|
|
143
|
-
* `PlCheckbox` and `PlRadioGroup` make everywhere else: a tick says "and", a dot
|
|
144
|
-
* says "instead of".
|
|
145
|
-
*/
|
|
146
|
-
export function PlMenuRadioItem({ value, endIcon, shortcut, description, color, closeOnClick = false, disabled = false, label, children, className, style }) {
|
|
147
|
-
const { size, density } = React.useContext(MenuContext);
|
|
148
|
-
const slots = color ? surfaceSlots(color, 0) : undefined;
|
|
149
|
-
return (_jsxs(BaseUIMenu.RadioItem, { value: value, disabled: disabled, label: label, closeOnClick: closeOnClick, className: rowClasses(size, density, Boolean(color), className), style: slots || style ? { ...slots, ...style } : undefined, children: [_jsx("span", { className: cx(slotClasses, 'text-(--p-accent)'), children: _jsx(BaseUIMenu.RadioItemIndicator, { className: "flex items-center justify-center", children: _jsx(DotIcon, {}) }) }), _jsx(RowBody, { description: description, size: size, children: children }), hasContent(endIcon) ? (_jsx("span", { className: cx(slotClasses, 'text-(--plass-muted-fg)'), children: endIcon })) : null, hasContent(shortcut) ? _jsx("span", { className: shortcutClasses(size), children: shortcut }) : null] }));
|
|
150
|
-
}
|
|
151
|
-
/** A named run of rows. The label is a heading, not a row — it cannot be picked. */
|
|
152
|
-
export function PlMenuGroup({ label, children, className }) {
|
|
153
|
-
const { size, density } = React.useContext(MenuContext);
|
|
154
|
-
return (_jsxs(BaseUIMenu.Group, { className: className, children: [hasContent(label) ? (_jsx(BaseUIMenu.GroupLabel, { className: cx(rowPaddingClasses[density][size], metaTextClasses[size], 'font-semibold tracking-wide text-(--plass-muted-fg) uppercase'), children: label })) : null, children] }));
|
|
155
|
-
}
|
|
156
|
-
/** The hairline between two runs of rows. */
|
|
157
|
-
export function PlMenuSeparator({ className, ...props }) {
|
|
158
|
-
return (_jsx(BaseUIMenu.Separator, { className: cx('-mx-1 my-1 h-px bg-(--plass-divider)', className), ...props }));
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* A menu inside a menu.
|
|
162
|
-
*
|
|
163
|
-
* The row that opens it is the same row every other item is, wearing a chevron —
|
|
164
|
-
* and it opens on hover, on <kbd>Enter</kbd> and on the arrow key that points at
|
|
165
|
-
* it, all of which is Base UI's. What is here is the surface and the glyph.
|
|
166
|
-
*
|
|
167
|
-
* Nesting is unlimited: a `PlMenuSubmenu` renders its children inside a popup
|
|
168
|
-
* that is itself a menu, so a submenu of a submenu needs no different component.
|
|
169
|
-
*/
|
|
170
|
-
export function PlMenuSubmenu({ label, startIcon, disabled = false, side = 'right', sideOffset = 4, children, className, style }) {
|
|
171
|
-
const { size, density, color } = React.useContext(MenuContext);
|
|
172
|
-
return (_jsxs(BaseUIMenu.SubmenuRoot, { children: [_jsxs(BaseUIMenu.SubmenuTrigger, { disabled: disabled, className: rowClasses(size, density, false), children: [hasContent(startIcon) ? (_jsx("span", { className: cx(slotClasses, 'text-(--plass-muted-fg)'), children: startIcon })) : null, _jsx("span", { className: "min-w-0 flex-1 truncate text-start", children: label }), _jsx("span", { className: cx(slotClasses, 'text-(--plass-muted-fg) -rotate-90'), children: _jsx(ChevronIcon, {}) })] }), _jsx(BaseUIMenu.Portal, { children: _jsx(BaseUIMenu.Positioner, { className: "plass-portal z-50 [outline:none]", side: side, sideOffset: sideOffset, align: "start", children: _jsx(BaseUIMenu.Popup, { className: cx(popupClasses, radiusClasses[size], controlTextLeadingClasses[size], className), style: { ...surfaceSlots(color, 3), ...style }, children: children }) }) })] }));
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* A list of actions that appears when something is pressed.
|
|
176
|
-
*
|
|
177
|
-
* Everything that makes a menu a menu rather than a floating list of `<div>`s is
|
|
178
|
-
* Base UI's: roving focus with the arrow keys, <kbd>Home</kbd> and
|
|
179
|
-
* <kbd>End</kbd>, typeahead, <kbd>Esc</kbd>, closing on an outside click,
|
|
180
|
-
* restoring focus to the trigger, submenus opening on hover with the safe
|
|
181
|
-
* triangle so a diagonal reach does not close them, and the `menu` / `menuitem`
|
|
182
|
-
* roles that make any of it mean something to a screen reader. What is here is
|
|
183
|
-
* the surface, the ladders and the row layout.
|
|
184
|
-
*
|
|
185
|
-
* The rows are **composed rather than passed as data** — the opposite of
|
|
186
|
-
* `PlSelect`, and deliberately. A select's options are values from a list a
|
|
187
|
-
* caller already has; a menu's rows are *code*, each one a different handler, a
|
|
188
|
-
* different icon, sometimes a submenu. Data would mean an `items` type with a
|
|
189
|
-
* variant for every shape a row can take, which is a component tree spelled as a
|
|
190
|
-
* discriminated union.
|
|
191
|
-
*/
|
|
192
|
-
export function PlMenu({ size = 'md', color = 'primary', density = 'default', trigger, open, defaultOpen, onOpenChange, side = 'bottom', align = 'start', sideOffset = 6, modal = true, openOnHover = false, loopFocus = true, disabled = false, className, style, children }) {
|
|
193
|
-
const context = React.useMemo(() => ({ size, color, density }), [size, color, density]);
|
|
194
|
-
return (_jsx(MenuContext.Provider, { value: context, children: _jsxs(BaseUIMenu.Root, { open: open, defaultOpen: defaultOpen, onOpenChange: (next) => onOpenChange?.(next), modal: modal, loopFocus: loopFocus, disabled: disabled, children: [trigger ? (_jsx(BaseUIMenu.Trigger, { render: trigger, openOnHover: openOnHover, disabled: disabled })) : null, _jsx(BaseUIMenu.Portal, { children: _jsx(BaseUIMenu.Positioner, { className: "plass-portal z-50 [outline:none]", side: side, align: align, sideOffset: sideOffset, children: _jsx(BaseUIMenu.Popup, { className: cx(popupClasses, radiusClasses[size], controlTextLeadingClasses[size], className), style: { ...surfaceSlots(color, 3), ...style }, children: children }) }) })] }) }));
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* The same menu, opened by a right-click or a long press instead of by a button.
|
|
198
|
-
*
|
|
199
|
-
* It takes the rows as `content` and the area as `children`, which is
|
|
200
|
-
* `PlTooltip`'s shape rather than `PlMenu`'s — because here the trigger is not
|
|
201
|
-
* one element you hand over, it is a region of the page, and the region is the
|
|
202
|
-
* thing being wrapped. Base UI positions the popup at the pointer rather than
|
|
203
|
-
* against an anchor, and the long press is what makes it reachable on a touch
|
|
204
|
-
* screen at all.
|
|
205
|
-
*/
|
|
206
|
-
export function PlContextMenu({ size = 'md', color = 'primary', density = 'default', content, children, open, defaultOpen, onOpenChange, loopFocus = true, disabled = false, className, style }) {
|
|
207
|
-
const context = React.useMemo(() => ({ size, color, density }), [size, color, density]);
|
|
208
|
-
return (_jsx(MenuContext.Provider, { value: context, children: _jsxs(BaseUIContextMenu.Root, { open: open, defaultOpen: defaultOpen, onOpenChange: (next) => onOpenChange?.(next), loopFocus: loopFocus, disabled: disabled, children: [_jsx(BaseUIContextMenu.Trigger, { children: children }), _jsx(BaseUIContextMenu.Portal, { children: _jsx(BaseUIContextMenu.Positioner, { className: "plass-portal z-50 [outline:none]", children: _jsx(BaseUIContextMenu.Popup, { className: cx(popupClasses, radiusClasses[size], controlTextLeadingClasses[size], className), style: { ...surfaceSlots(color, 3), ...style }, children: content }) }) })] }) }));
|
|
209
|
-
}
|
|
1
|
+
"use client";import{jsx as e,jsxs as s,Fragment as l}from"react/jsx-runtime";import*as n from"react";import{Menu as a}from"@base-ui/react/menu";import{ContextMenu as t}from"@base-ui/react/context-menu";import{MenuContext as o}from"../../internal/menu.js";import{CheckIcon as r,ChevronIcon as i,DotIcon as c}from"../../internal/icons.js";import{controlTextLeadingClasses as d,cx as p,gapClasses as u,glassClasses as m,hasContent as h,iconClasses as x,metaTextClasses as f,radiusClasses as g,surfaceSlots as y,transitionClasses as b}from"../../internal/styles.js";const C=/* @__PURE__ */[m,"max-h-[min(24rem,var(--available-height))] min-w-40 overflow-y-auto overscroll-contain","border bg-(--plass-glass-press) p-1","[border-color:var(--plass-glass-line)]","[box-shadow:var(--plass-shadow-3),var(--plass-gloss-glass)]","[outline:none]","[transition:opacity_var(--plass-duration)_var(--plass-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" "),N={default:{xs:"px-1.5 py-0.5",sm:"px-2 py-1",md:"px-2.5 py-1.5",lg:"px-3 py-2",xl:"px-3.5 py-2.5"},compact:{xs:"px-1 py-0.5",sm:"px-1.5 py-0.5",md:"px-2 py-1",lg:"px-2.5 py-1",xl:"px-3 py-1.5"}},v={xs:g.xs,sm:g.xs,md:g.sm,lg:g.sm,xl:g.md};function rowClasses(e,s,l,n){return p("relative flex w-full cursor-pointer items-center select-none",l?"text-(--p-accent)":"text-(--plass-fg)",N[s][e],v[e],u[e],d[e],b,x,"data-[highlighted]:bg-(--p-soft-hover)","data-[popup-open]:bg-(--p-soft)","data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50","[outline:none]",n)}const k="flex h-[1lh] w-[1.2em] shrink-0 items-center justify-center";function shortcutClasses(e){return p("ms-2 shrink-0 text-(--plass-muted-fg) tabular-nums",f[e])}function RowBody({children:l,description:n,size:a}){return h(n)?s("span",{className:"flex min-w-0 flex-1 flex-col text-start",children:[e("span",{className:"truncate",children:l}),e("span",{className:p("truncate text-(--plass-muted-fg)",f[a]),children:n})]}):e("span",{className:"min-w-0 flex-1 truncate text-start",children:l})}export function PlMenuItem({onClick:t,href:r,target:i,startIcon:c,endIcon:d,shortcut:u,description:m,color:x,closeOnClick:f=!0,disabled:g=!1,label:b,children:C,className:N,style:v}){const{size:w,density:O}=n.useContext(o),P=s(l,{children:[h(c)?e("span",{className:p(k,"text-(--plass-muted-fg)"),children:c}):null,e(RowBody,{description:m,size:w,children:C}),h(d)?e("span",{className:p(k,"text-(--plass-muted-fg)"),children:d}):null,h(u)?e("span",{className:shortcutClasses(w),children:u}):null]}),z=x?y(x,0):void 0,I=z||v?{...z,...v}:void 0;return void 0!==r?e(a.LinkItem,{href:r,target:i,label:b,closeOnClick:f,onClick:t,className:rowClasses(w,O,Boolean(x),N),style:I,children:P}):e(a.Item,{disabled:g,label:b,closeOnClick:f,onClick:t,className:rowClasses(w,O,Boolean(x),N),style:I,children:P})}export function PlMenuCheckboxItem({checked:l,defaultChecked:t,onCheckedChange:i,endIcon:c,shortcut:d,description:u,color:m,closeOnClick:x=!1,disabled:f=!1,label:g,children:b,className:C,style:N}){const{size:v,density:w}=n.useContext(o),O=m?y(m,0):void 0;return s(a.CheckboxItem,{checked:l,defaultChecked:t,onCheckedChange:e=>i?.(e),disabled:f,label:g,closeOnClick:x,className:rowClasses(v,w,Boolean(m),C),style:O||N?{...O,...N}:void 0,children:[e("span",{className:p(k,"text-(--p-accent)"),children:e(a.CheckboxItemIndicator,{className:"flex items-center justify-center",children:e(r,{})})}),e(RowBody,{description:u,size:v,children:b}),h(c)?e("span",{className:p(k,"text-(--plass-muted-fg)"),children:c}):null,h(d)?e("span",{className:shortcutClasses(v),children:d}):null]})}export function PlMenuRadioGroup({value:s,defaultValue:l,onValueChange:n,disabled:t=!1,children:o,className:r}){return e(a.RadioGroup,{value:s,defaultValue:l,onValueChange:e=>n?.(e),disabled:t,className:r,children:o})}export function PlMenuRadioItem({value:l,endIcon:t,shortcut:r,description:i,color:d,closeOnClick:u=!1,disabled:m=!1,label:x,children:f,className:g,style:b}){const{size:C,density:N}=n.useContext(o),v=d?y(d,0):void 0;return s(a.RadioItem,{value:l,disabled:m,label:x,closeOnClick:u,className:rowClasses(C,N,Boolean(d),g),style:v||b?{...v,...b}:void 0,children:[e("span",{className:p(k,"text-(--p-accent)"),children:e(a.RadioItemIndicator,{className:"flex items-center justify-center",children:e(c,{})})}),e(RowBody,{description:i,size:C,children:f}),h(t)?e("span",{className:p(k,"text-(--plass-muted-fg)"),children:t}):null,h(r)?e("span",{className:shortcutClasses(C),children:r}):null]})}export function PlMenuGroup({label:l,children:t,className:r}){const{size:i,density:c}=n.useContext(o);return s(a.Group,{className:r,children:[h(l)?e(a.GroupLabel,{className:p(N[c][i],f[i],"font-semibold tracking-wide text-(--plass-muted-fg) uppercase"),children:l}):null,t]})}export function PlMenuSeparator({className:s,...l}){return e(a.Separator,{className:p("-mx-1 my-1 h-px bg-(--plass-divider)",s),...l})}export function PlMenuSubmenu({label:l,startIcon:t,disabled:r=!1,side:c="right",sideOffset:u=4,children:m,className:x,style:f}){const{size:b,density:N,color:v}=n.useContext(o);return s(a.SubmenuRoot,{children:[s(a.SubmenuTrigger,{disabled:r,className:rowClasses(b,N,!1),children:[h(t)?e("span",{className:p(k,"text-(--plass-muted-fg)"),children:t}):null,e("span",{className:"min-w-0 flex-1 truncate text-start",children:l}),e("span",{className:p(k,"text-(--plass-muted-fg) -rotate-90"),children:e(i,{})})]}),e(a.Portal,{children:e(a.Positioner,{className:"plass-portal z-50 [outline:none]",side:c,sideOffset:u,align:"start",children:e(a.Popup,{className:p(C,g[b],d[b],x),style:{...y(v,3),...f},children:m})})})]})}export function PlMenu({size:l="md",color:t="primary",density:r="default",trigger:i,open:c,defaultOpen:u,onOpenChange:m,side:h="bottom",align:x="start",sideOffset:f=6,modal:b=!0,openOnHover:N=!1,loopFocus:v=!0,disabled:k=!1,className:w,style:O,children:P}){const z=n.useMemo(()=>({size:l,color:t,density:r}),[l,t,r]);return e(o.Provider,{value:z,children:s(a.Root,{open:c,defaultOpen:u,onOpenChange:e=>m?.(e),modal:b,loopFocus:v,disabled:k,children:[i?e(a.Trigger,{render:i,openOnHover:N,disabled:k}):null,e(a.Portal,{children:e(a.Positioner,{className:"plass-portal z-50 [outline:none]",side:h,align:x,sideOffset:f,children:e(a.Popup,{className:p(C,g[l],d[l],w),style:{...y(t,3),...O},children:P})})})]})})}export function PlContextMenu({size:l="md",color:a="primary",density:r="default",content:i,children:c,open:u,defaultOpen:m,onOpenChange:h,loopFocus:x=!0,disabled:f=!1,className:b,style:N}){const v=n.useMemo(()=>({size:l,color:a,density:r}),[l,a,r]);return e(o.Provider,{value:v,children:s(t.Root,{open:u,defaultOpen:m,onOpenChange:e=>h?.(e),loopFocus:x,disabled:f,children:[e(t.Trigger,{children:c}),e(t.Portal,{children:e(t.Positioner,{className:"plass-portal z-50 [outline:none]",children:e(t.Popup,{className:p(C,g[l],d[l],b),style:{...y(a,3),...N},children:i})})})]})})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export{PlContextMenu,PlMenu,PlMenuCheckboxItem,PlMenuGroup,PlMenuItem,PlMenuRadioGroup,PlMenuRadioItem,PlMenuSeparator,PlMenuSubmenu}from"./PlMenu.js";
|
|
@@ -1,150 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { Dialog as BaseUIDialog } from '@base-ui/react/dialog';
|
|
3
|
-
import { CloseIcon } from '../../internal/icons.js';
|
|
4
|
-
import { focusRingClasses, glassClasses, hasContent, metaTextClasses, radiusClasses, sheetBodyClasses, sheetHeaderGapClasses, sheetLineClasses, sheetPaddingXClasses, sheetPaddingYClasses, sheetSectionGapClasses, sheetTitleClasses, surfaceSlots } from '../../internal/styles.js';
|
|
5
|
-
/**
|
|
6
|
-
* How wide the sheet is allowed to get, per `size`.
|
|
7
|
-
*
|
|
8
|
-
* `size` and the width are one axis here rather than two. A second five-value
|
|
9
|
-
* scale spelled `maxWidth` would be a second spelling of an idea the library
|
|
10
|
-
* already has a word for, and the case it exists for — "small type, wide sheet"
|
|
11
|
-
* — is what the `width` escape hatch is.
|
|
12
|
-
*
|
|
13
|
-
* The steps are wider apart than the control ladder because they answer a
|
|
14
|
-
* different question: not how big is this thing, but how long a line of text is
|
|
15
|
-
* comfortable inside it.
|
|
16
|
-
*/
|
|
17
|
-
const maxWidthClasses = {
|
|
18
|
-
xs: 'max-w-80',
|
|
19
|
-
sm: 'max-w-96',
|
|
20
|
-
md: 'max-w-lg',
|
|
21
|
-
lg: 'max-w-2xl',
|
|
22
|
-
xl: 'max-w-4xl'
|
|
23
|
-
};
|
|
24
|
-
/**
|
|
25
|
-
* The sheet, and — with the PlSelect popup — one of the two surfaces in the
|
|
26
|
-
* library that is *supposed* to float. So unlike everything else it carries a
|
|
27
|
-
* shadow by default, at level 3.
|
|
28
|
-
*
|
|
29
|
-
* It is the glass at its most opaque, because what is behind it is arbitrary:
|
|
30
|
-
* a modal floats over whatever the page happens to be, and a 62%-translucent
|
|
31
|
-
* pane over a photograph is a pane you read the photograph through.
|
|
32
|
-
*
|
|
33
|
-
* There is no `elevation` prop for the same reason there is no `variant`: a
|
|
34
|
-
* modal that could be told to sit flat on the page would be a modal that could
|
|
35
|
-
* be told to stop being one.
|
|
36
|
-
*/
|
|
37
|
-
const popupClasses = /* @__PURE__ */ [
|
|
38
|
-
glassClasses,
|
|
39
|
-
'relative flex w-full flex-col overflow-hidden',
|
|
40
|
-
'border text-(--plass-fg) bg-(--plass-glass-press)',
|
|
41
|
-
'[border-color:var(--plass-glass-line)]',
|
|
42
|
-
'[box-shadow:var(--plass-shadow-4),var(--plass-gloss-glass)]',
|
|
43
|
-
'[outline:none]',
|
|
44
|
-
// Opacity only. A modal that scales or slides in drags its own text across
|
|
45
|
-
// the screen for 200ms, which is the exact thing the house style is against —
|
|
46
|
-
// and unlike a control, this one is full of text.
|
|
47
|
-
'[transition:opacity_var(--plass-duration)_var(--plass-ease)]',
|
|
48
|
-
'data-[starting-style]:opacity-0 data-[ending-style]:opacity-0'
|
|
49
|
-
].join(' ');
|
|
50
|
-
const backdropClasses = /* @__PURE__ */ [
|
|
51
|
-
'fixed inset-0 z-50 bg-(--plass-scrim)',
|
|
52
|
-
'[backdrop-filter:blur(2px)] [-webkit-backdrop-filter:blur(2px)]',
|
|
53
|
-
'[transition:opacity_var(--plass-duration)_var(--plass-ease)]',
|
|
54
|
-
'data-[starting-style]:opacity-0 data-[ending-style]:opacity-0'
|
|
55
|
-
].join(' ');
|
|
56
|
-
/**
|
|
57
|
-
* Closes the modal it is inside.
|
|
58
|
-
*
|
|
59
|
-
* Exported because an uncontrolled modal has no `setOpen` for its Cancel button
|
|
60
|
-
* to call, and the alternative — making every modal controlled — is a piece of
|
|
61
|
-
* state per modal that exists only to answer a button.
|
|
62
|
-
*
|
|
63
|
-
* `render` is Base UI's own escape hatch, so a real Plass button dismisses:
|
|
64
|
-
* `<PlModalClose render={<PlButton variant="ghost">Cancel</PlButton>} />`.
|
|
65
|
-
*/
|
|
66
|
-
export const PlModalClose = BaseUIDialog.Close;
|
|
67
|
-
/**
|
|
68
|
-
* A sheet that takes the page away until it is answered.
|
|
69
|
-
*
|
|
70
|
-
* The sections are props rather than compound sub-components, exactly as they
|
|
71
|
-
* are on PlCard: the arrangement of a modal is fixed — heading, description,
|
|
72
|
-
* body, actions — and what a caller wants to decide is what goes in each slot.
|
|
73
|
-
* Base UI owns everything hard about it: the focus trap, the scroll lock, the
|
|
74
|
-
* `aria-labelledby` / `aria-describedby` wiring, restoring focus to the trigger,
|
|
75
|
-
* and the inert page behind.
|
|
76
|
-
*
|
|
77
|
-
* What is left here is the surface, the width ladder and the scroll behaviour —
|
|
78
|
-
* the header and the actions stay put while only the body scrolls, which is why
|
|
79
|
-
* `dividers` matters more here than on a PlCard.
|
|
80
|
-
*/
|
|
81
|
-
export function PlModal({ size = 'md', color = 'primary', density = 'default', open, defaultOpen, onOpenChange, trigger, title, description, actions, dividers = false, showClose = true, closeLabel = 'Close', width, fullWidth = true, fullScreen = false, modal = true, dismissible = true, className, style, children, ...props }) {
|
|
82
|
-
const insetX = sheetPaddingXClasses[density][size];
|
|
83
|
-
const insetY = sheetPaddingYClasses[density][size];
|
|
84
|
-
// With dividers the lines have to reach both edges, so the sheet gives up its
|
|
85
|
-
// padding and every section takes it on instead — the same trade PlCard makes.
|
|
86
|
-
const sectionClasses = dividers ? `${insetX} ${insetY}` : insetX;
|
|
87
|
-
const hasHeader = hasContent(title) || hasContent(description);
|
|
88
|
-
const hasActions = hasContent(actions);
|
|
89
|
-
return (_jsxs(BaseUIDialog.Root, { open: open, defaultOpen: defaultOpen, modal: modal, disablePointerDismissal: !dismissible, onOpenChange: (next, details) => {
|
|
90
|
-
// `disablePointerDismissal` covers the click outside; Escape has no prop
|
|
91
|
-
// of its own, so it is cancelled here by the reason it arrives with.
|
|
92
|
-
if (!dismissible && !next && details.reason === 'escape-key') {
|
|
93
|
-
details.cancel();
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
onOpenChange?.(next);
|
|
97
|
-
}, children: [trigger ? _jsx(BaseUIDialog.Trigger, { render: trigger }) : null, _jsxs(BaseUIDialog.Portal, { children: [_jsx(BaseUIDialog.Backdrop, { className: `plass-portal ${backdropClasses}` }), _jsx(BaseUIDialog.Viewport, { className: [
|
|
98
|
-
'plass-portal fixed inset-0 z-50 flex justify-center',
|
|
99
|
-
// `items-center` alone would clip the top of a modal taller than the
|
|
100
|
-
// viewport, because a centred flex item cannot scroll past its own
|
|
101
|
-
// container's start edge. The popup caps its height instead and
|
|
102
|
-
// scrolls its body, so the header and the actions stay put.
|
|
103
|
-
fullScreen ? 'items-stretch' : 'items-center p-4'
|
|
104
|
-
].join(' '), children: _jsxs(BaseUIDialog.Popup, { className: [
|
|
105
|
-
popupClasses,
|
|
106
|
-
sheetBodyClasses[size],
|
|
107
|
-
fullScreen
|
|
108
|
-
? 'h-full max-w-none rounded-none'
|
|
109
|
-
: `max-h-full ${radiusClasses[size]} ${width === undefined ? maxWidthClasses[size] : ''}`,
|
|
110
|
-
!fullScreen && !fullWidth ? 'w-auto' : '',
|
|
111
|
-
dividers ? '' : `${insetY} ${sheetSectionGapClasses[size]}`,
|
|
112
|
-
className ?? ''
|
|
113
|
-
]
|
|
114
|
-
.filter(Boolean)
|
|
115
|
-
.join(' '), style: {
|
|
116
|
-
...surfaceSlots(color, 3),
|
|
117
|
-
...(width === undefined
|
|
118
|
-
? null
|
|
119
|
-
: { maxWidth: typeof width === 'number' ? `${width}px` : width }),
|
|
120
|
-
...style
|
|
121
|
-
}, ...props, children: [hasHeader || showClose ? (_jsxs("div", { className: `flex shrink-0 items-start gap-3 ${sectionClasses}`, children: [_jsxs("div", { className: `flex min-w-0 flex-1 flex-col ${sheetHeaderGapClasses[size]}`, children: [hasContent(title) ? (_jsx(BaseUIDialog.Title, { className: `m-0 font-semibold ${sheetTitleClasses[size]}`, children: title })) : null, hasContent(description) ? (_jsx(BaseUIDialog.Description, { className: `m-0 text-(--plass-muted-fg) ${metaTextClasses[size]}`, children: description })) : null] }), showClose ? (_jsx(BaseUIDialog.Close, { "aria-label": closeLabel, className: [
|
|
122
|
-
'flex size-[1.6em] shrink-0 cursor-pointer items-center justify-center',
|
|
123
|
-
'rounded-full text-(--plass-muted-fg)',
|
|
124
|
-
'[&_svg]:size-[1.1em] [&_svg]:shrink-0',
|
|
125
|
-
'[transition:background-color_var(--plass-duration)_var(--plass-ease),color_var(--plass-duration)_var(--plass-ease)]',
|
|
126
|
-
'hover:bg-(--p-soft) hover:text-(--plass-fg)',
|
|
127
|
-
focusRingClasses
|
|
128
|
-
].join(' '), children: _jsx(CloseIcon, {}) })) : null] })) : null, hasContent(children) ? (_jsx("div", { className: [
|
|
129
|
-
'min-h-0 flex-1 overflow-y-auto overscroll-contain',
|
|
130
|
-
sectionClasses,
|
|
131
|
-
dividers && (hasHeader || showClose) ? sheetLineClasses : '',
|
|
132
|
-
// A scroll container clips at its padding box, and a focus
|
|
133
|
-
// ring is drawn 2px outside the control that owns it — so a
|
|
134
|
-
// field at the top or bottom of an unruled body would have its
|
|
135
|
-
// ring sliced off. The padding is room for the ring and the
|
|
136
|
-
// negative margin hands the space straight back, so nothing on
|
|
137
|
-
// the sheet moves. Only without `dividers`: with them the body
|
|
138
|
-
// already carries `insetY`, and pulling it up would drag the
|
|
139
|
-
// rule into the section above.
|
|
140
|
-
dividers ? '' : '-my-1 py-1'
|
|
141
|
-
]
|
|
142
|
-
.filter(Boolean)
|
|
143
|
-
.join(' '), children: children })) : null, hasActions ? (_jsx("div", { className: [
|
|
144
|
-
'flex shrink-0 flex-wrap items-center justify-end gap-2',
|
|
145
|
-
sectionClasses,
|
|
146
|
-
dividers ? sheetLineClasses : ''
|
|
147
|
-
]
|
|
148
|
-
.filter(Boolean)
|
|
149
|
-
.join(' '), children: actions })) : null] }) })] })] }));
|
|
150
|
-
}
|
|
1
|
+
"use client";import{jsx as e,jsxs as l}from"react/jsx-runtime";import{Dialog as s}from"@base-ui/react/dialog";import{CloseIcon as a}from"../../internal/icons.js";import{focusRingClasses as i,glassClasses as o,hasContent as r,metaTextClasses as t,radiusClasses as n,sheetBodyClasses as d,sheetHeaderGapClasses as c,sheetLineClasses as p,sheetPaddingXClasses as m,sheetPaddingYClasses as f,sheetSectionGapClasses as u,sheetTitleClasses as x,surfaceSlots as h}from"../../internal/styles.js";const g={xs:"max-w-80",sm:"max-w-96",md:"max-w-lg",lg:"max-w-2xl",xl:"max-w-4xl"},v=/* @__PURE__ */[o,"relative flex w-full flex-col overflow-hidden","border text-(--plass-fg) bg-(--plass-glass-press)","[border-color:var(--plass-glass-line)]","[box-shadow:var(--plass-shadow-4),var(--plass-gloss-glass)]","[outline:none]","[transition:opacity_var(--plass-duration)_var(--plass-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" "),y=/* @__PURE__ */["fixed inset-0 z-50 bg-(--plass-scrim)","[backdrop-filter:blur(2px)] [-webkit-backdrop-filter:blur(2px)]","[transition:opacity_var(--plass-duration)_var(--plass-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" ");export const PlModalClose=s.Close;export function PlModal({size:o="md",color:b="primary",density:w="default",open:j,defaultOpen:$,onOpenChange:N,trigger:k,title:_,description:C,actions:z,dividers:P=!1,showClose:B=!0,closeLabel:O="Close",width:D,fullWidth:M=!0,fullScreen:T=!1,modal:W=!0,dismissible:L=!0,className:R,style:S,children:V,...q}){const A=m[w][o],E=f[w][o],F=P?`${A} ${E}`:A,G=r(_)||r(C),H=r(z);return l(s.Root,{open:j,defaultOpen:$,modal:W,disablePointerDismissal:!L,onOpenChange:(e,l)=>{L||e||"escape-key"!==l.reason?N?.(e):l.cancel()},children:[k?e(s.Trigger,{render:k}):null,l(s.Portal,{children:[e(s.Backdrop,{className:`plass-portal ${y}`}),e(s.Viewport,{className:["plass-portal fixed inset-0 z-50 flex justify-center",T?"items-stretch":"items-center p-4"].join(" "),children:l(s.Popup,{className:[v,d[o],T?"h-full max-w-none rounded-none":`max-h-full ${n[o]} ${void 0===D?g[o]:""}`,T||M?"":"w-auto",P?"":`${E} ${u[o]}`,R??""].filter(Boolean).join(" "),style:{...h(b,3),...void 0===D?null:{maxWidth:"number"==typeof D?`${D}px`:D},...S},...q,children:[G||B?l("div",{className:`flex shrink-0 items-start gap-3 ${F}`,children:[l("div",{className:`flex min-w-0 flex-1 flex-col ${c[o]}`,children:[r(_)?e(s.Title,{className:`m-0 font-semibold ${x[o]}`,children:_}):null,r(C)?e(s.Description,{className:`m-0 text-(--plass-muted-fg) ${t[o]}`,children:C}):null]}),B?e(s.Close,{"aria-label":O,className:["flex size-[1.6em] shrink-0 cursor-pointer items-center justify-center","rounded-full text-(--plass-muted-fg)","[&_svg]:size-[1.1em] [&_svg]:shrink-0","[transition:background-color_var(--plass-duration)_var(--plass-ease),color_var(--plass-duration)_var(--plass-ease)]","hover:bg-(--p-soft) hover:text-(--plass-fg)",i].join(" "),children:e(a,{})}):null]}):null,r(V)?e("div",{className:["min-h-0 flex-1 overflow-y-auto overscroll-contain",F,P&&(G||B)?p:"",P?"":"-my-1 py-1"].filter(Boolean).join(" "),children:V}):null,H?e("div",{className:["flex shrink-0 flex-wrap items-center justify-end gap-2",F,P?p:""].filter(Boolean).join(" "),children:z}):null]})})]})]})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export{PlModal,PlModalClose}from"./PlModal.js";
|