plass-ui 1.0.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +189 -0
- package/README.md +2 -0
- package/dist/components/avatar/PlAvatar.js +1 -1
- package/dist/components/avatar-group/PlAvatarGroup.d.ts +47 -0
- package/dist/components/avatar-group/PlAvatarGroup.js +1 -0
- package/dist/components/avatar-group/index.d.ts +2 -0
- package/dist/components/avatar-group/index.js +1 -0
- package/dist/components/checkbox/PlCheckbox.d.ts +3 -1
- package/dist/components/checkbox/PlCheckbox.js +1 -1
- package/dist/components/color-picker/PlColorPicker.d.ts +88 -0
- package/dist/components/color-picker/PlColorPicker.js +1 -0
- package/dist/components/color-picker/index.d.ts +2 -0
- package/dist/components/color-picker/index.js +1 -0
- package/dist/components/combobox/PlCombobox.d.ts +4 -2
- package/dist/components/combobox/PlCombobox.js +1 -1
- package/dist/components/command-palette/PlCommandPalette.d.ts +89 -0
- package/dist/components/command-palette/PlCommandPalette.js +1 -0
- package/dist/components/command-palette/index.d.ts +2 -0
- package/dist/components/command-palette/index.js +1 -0
- package/dist/components/divider/PlDivider.js +1 -1
- package/dist/components/drawer/PlDrawer.d.ts +4 -2
- package/dist/components/drawer/PlDrawer.js +1 -1
- package/dist/components/fieldset/PlFieldset.d.ts +35 -0
- package/dist/components/fieldset/PlFieldset.js +1 -0
- package/dist/components/fieldset/index.d.ts +2 -0
- package/dist/components/fieldset/index.js +1 -0
- package/dist/components/footer/PlFooter.d.ts +90 -0
- package/dist/components/footer/PlFooter.js +1 -0
- package/dist/components/footer/index.d.ts +2 -0
- package/dist/components/footer/index.js +1 -0
- package/dist/components/form/PlForm.d.ts +61 -0
- package/dist/components/form/PlForm.js +1 -0
- package/dist/components/form/index.d.ts +2 -0
- package/dist/components/form/index.js +1 -0
- package/dist/components/header/PlHeader.d.ts +124 -0
- package/dist/components/header/PlHeader.js +1 -0
- package/dist/components/header/index.d.ts +2 -0
- package/dist/components/header/index.js +1 -0
- package/dist/components/menu/PlMenu.d.ts +4 -2
- package/dist/components/menu/PlMenu.js +1 -1
- package/dist/components/menubar/PlMenubar.d.ts +60 -0
- package/dist/components/menubar/PlMenubar.js +1 -0
- package/dist/components/menubar/index.d.ts +2 -0
- package/dist/components/menubar/index.js +1 -0
- package/dist/components/modal/PlModal.d.ts +4 -2
- package/dist/components/modal/PlModal.js +1 -1
- package/dist/components/navigation-menu/PlNavigationMenu.d.ts +103 -0
- package/dist/components/navigation-menu/PlNavigationMenu.js +1 -0
- package/dist/components/navigation-menu/index.d.ts +2 -0
- package/dist/components/navigation-menu/index.js +1 -0
- package/dist/components/number-field/PlNumberField.d.ts +4 -2
- package/dist/components/number-field/PlNumberField.js +1 -1
- package/dist/components/otp-field/PlOtpField.d.ts +3 -1
- package/dist/components/otp-field/PlOtpField.js +1 -1
- package/dist/components/overlay/PlOverlay.d.ts +4 -2
- package/dist/components/overlay/PlOverlay.js +1 -1
- package/dist/components/page-layout/PlPageLayout.d.ts +139 -0
- package/dist/components/page-layout/PlPageLayout.js +1 -0
- package/dist/components/page-layout/index.d.ts +2 -0
- package/dist/components/page-layout/index.js +1 -0
- package/dist/components/radio-group/PlRadioGroup.d.ts +3 -1
- package/dist/components/radio-group/PlRadioGroup.js +1 -1
- package/dist/components/scroll-zone/PlScrollZone.d.ts +35 -15
- package/dist/components/scroll-zone/PlScrollZone.js +1 -1
- package/dist/components/select/PlSelect.d.ts +3 -1
- package/dist/components/select/PlSelect.js +1 -1
- package/dist/components/sidebar/PlSidebar.d.ts +141 -0
- package/dist/components/sidebar/PlSidebar.js +1 -0
- package/dist/components/sidebar/PlSidebarTrigger.d.ts +34 -0
- package/dist/components/sidebar/PlSidebarTrigger.js +1 -0
- package/dist/components/sidebar/index.d.ts +4 -0
- package/dist/components/sidebar/index.js +1 -0
- package/dist/components/switch/PlSwitch.d.ts +3 -1
- package/dist/components/switch/PlSwitch.js +1 -1
- package/dist/components/text-field/PlTextField.d.ts +3 -1
- package/dist/components/text-field/PlTextField.js +1 -1
- package/dist/components/text-link/PlTextLink.d.ts +11 -2
- package/dist/components/text-link/PlTextLink.js +1 -1
- package/dist/components/toast/PlToast.d.ts +10 -0
- package/dist/components/toast/PlToast.js +1 -1
- package/dist/components/toggle/PlToggle.d.ts +55 -0
- package/dist/components/toggle/PlToggle.js +1 -0
- package/dist/components/toggle/PlToggleGroup.d.ts +48 -0
- package/dist/components/toggle/PlToggleGroup.js +1 -0
- package/dist/components/toggle/index.d.ts +4 -0
- package/dist/components/toggle/index.js +1 -0
- package/dist/components/transfer/PlTransfer.d.ts +55 -0
- package/dist/components/transfer/PlTransfer.js +1 -0
- package/dist/components/transfer/index.d.ts +2 -0
- package/dist/components/transfer/index.js +1 -0
- package/dist/css/avatar-group.css +2 -0
- package/dist/css/color-picker.css +2 -0
- package/dist/css/command-palette.css +2 -0
- package/dist/css/fieldset.css +2 -0
- package/dist/css/footer.css +2 -0
- package/dist/css/form.css +2 -0
- package/dist/css/header.css +2 -0
- package/dist/css/menubar.css +2 -0
- package/dist/css/navigation-menu.css +2 -0
- package/dist/css/page-layout.css +2 -0
- package/dist/css/sidebar.css +2 -0
- package/dist/css/toggle.css +2 -0
- package/dist/css/transfer.css +2 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +1 -1
- package/dist/internal/avatar-group.d.ts +25 -0
- package/dist/internal/avatar-group.js +2 -0
- package/dist/internal/color.d.ts +109 -0
- package/dist/internal/color.js +1 -0
- package/dist/internal/link.d.ts +18 -0
- package/dist/internal/link.js +1 -0
- package/dist/internal/page-layout.d.ts +140 -0
- package/dist/internal/page-layout.js +1 -0
- package/dist/internal/picker.d.ts +4 -2
- package/dist/internal/picker.js +1 -1
- package/dist/internal/search.d.ts +31 -0
- package/dist/internal/search.js +1 -0
- package/dist/internal/styles.d.ts +9 -0
- package/dist/internal/styles.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/types.d.ts +72 -0
- package/package.json +3 -3
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassElevation, PlassStyleProps, PlassVariant } from '../../types.js';
|
|
3
|
+
export interface PlToggleProps extends PlassStyleProps, Omit<React.ComponentPropsWithoutRef<'button'>, 'color' | 'value'> {
|
|
4
|
+
/**
|
|
5
|
+
* What the key is made of while it is **off**. On is always the colour family
|
|
6
|
+
* asserting itself, whichever material was asked for.
|
|
7
|
+
*
|
|
8
|
+
* - `solid` — the densest clear glass, which fills with the family's gradient
|
|
9
|
+
* when it goes on. The loudest, for a toggle a screen is steered by.
|
|
10
|
+
* - `glass` — the canonical sheet with a hairline round it. The default.
|
|
11
|
+
* - `ghost` — nothing at all until the pointer arrives or it goes on. What a
|
|
12
|
+
* toolbar wants.
|
|
13
|
+
* @default 'glass'
|
|
14
|
+
*/
|
|
15
|
+
variant?: PlassVariant;
|
|
16
|
+
/** Whether it is on. Use with `onPressedChange` for a controlled toggle. */
|
|
17
|
+
pressed?: boolean;
|
|
18
|
+
/** Whether it starts on, for an uncontrolled one. @default false */
|
|
19
|
+
defaultPressed?: boolean;
|
|
20
|
+
onPressedChange?: (pressed: boolean) => void;
|
|
21
|
+
/** Identifies the toggle inside a `PlToggleGroup`. */
|
|
22
|
+
value?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Drop shadow depth. `0` — the default, and one below a `PlButton`'s — is
|
|
25
|
+
* flat: a toggle is a state rather than an action, and a state does not float
|
|
26
|
+
* off the page waiting to be taken.
|
|
27
|
+
* @default 0
|
|
28
|
+
*/
|
|
29
|
+
elevation?: PlassElevation;
|
|
30
|
+
/** Content placed before the label. Sized in `em`, so it tracks the label. */
|
|
31
|
+
startIcon?: React.ReactNode;
|
|
32
|
+
/** Content placed after the label. */
|
|
33
|
+
endIcon?: React.ReactNode;
|
|
34
|
+
/** Stretches to the width of the container. */
|
|
35
|
+
fullWidth?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The label. Left out, the toggle goes square around whatever icon it was
|
|
38
|
+
* given — which is what a toolbar toggle is. An icon-only toggle still needs
|
|
39
|
+
* an `aria-label`.
|
|
40
|
+
*/
|
|
41
|
+
children?: React.ReactNode;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A button that stays down.
|
|
45
|
+
*
|
|
46
|
+
* The difference from a `PlSwitch` is what the press *is*: a switch changes a
|
|
47
|
+
* setting and the change is the point; a toggle changes the state of the thing
|
|
48
|
+
* beside it — bold on the selected words, the grid on the canvas, the filter on
|
|
49
|
+
* the list. The difference from a `PlCheckbox` is that this one is a control
|
|
50
|
+
* rather than an answer, so it never goes in a form.
|
|
51
|
+
*
|
|
52
|
+
* Base UI's Toggle owns `aria-pressed` and the controlled/uncontrolled pair.
|
|
53
|
+
* What is left here is the surface, and the rule that off is neutral.
|
|
54
|
+
*/
|
|
55
|
+
export declare const PlToggle: React.ForwardRefExoticComponent<PlToggleProps & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsxs as s}from"react/jsx-runtime";import*as e from"react";import{Toggle as o}from"@base-ui/react/toggle";import{ButtonGroupContext as a}from"../../internal/button-group.js";import{controlHeightClasses as l,controlSlots as r,controlSquareClasses as t,controlTextClasses as p,disabledClasses as i,focusRingClasses as n,gapClasses as v,glassClasses as g,hasContent as d,iconClasses as h,paddingXClasses as x,radiusClasses as c,transitionClasses as f}from"../../internal/styles.js";const b={xs:`${l.xs} ${v.xs} ${c.xs} ${p.xs}`,sm:`${l.sm} ${v.sm} ${c.sm} ${p.sm}`,md:`${l.md} ${v.md} ${c.md} ${p.md}`,lg:`${l.lg} ${v.lg} ${c.lg} ${p.lg}`,xl:`${l.xl} ${v.xl} ${c.xl} ${p.xl}`},m={xs:`${t.xs} px-0`,sm:`${t.sm} px-0`,md:`${t.md} px-0`,lg:`${t.lg} px-0`,xl:`${t.xl} px-0`},$=/* @__PURE__ */["relative inline-flex shrink-0 select-none items-center justify-center","whitespace-nowrap align-middle font-semibold leading-none","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",f,n,h].join(" "),u={solid:/* @__PURE__ */[g,"text-(--plass-muted-fg) bg-(--plass-glass-hover)","[box-shadow:var(--p-elev),var(--plass-gloss-glass)]"].join(" "),glass:/* @__PURE__ */[g,"border text-(--plass-muted-fg) bg-(--plass-glass)","[border-color:var(--plass-glass-line)]","[box-shadow:var(--p-elev),var(--plass-gloss-glass)]"].join(" "),ghost:"text-(--plass-muted-fg) bg-transparent"},w={solid:/* @__PURE__ */["hover:bg-(--plass-glass-press) hover:text-(--plass-fg)","hover:[box-shadow:var(--p-elev-hover),var(--plass-gloss-glass)]","active:[box-shadow:var(--p-elev-press),var(--plass-gloss-glass)]"].join(" "),glass:/* @__PURE__ */["hover:bg-(--plass-glass-hover) hover:text-(--plass-fg) hover:[border-color:var(--p-line)]","hover:[box-shadow:var(--p-elev-hover),var(--plass-gloss-glass)]","active:bg-(--plass-glass-press)","active:[box-shadow:var(--p-elev-press),var(--plass-gloss-glass)]"].join(" "),ghost:"hover:bg-(--p-soft) hover:text-(--plass-fg) active:bg-(--p-soft-hover)"},j={solid:/* @__PURE__ */["text-(--p-on-solid) [background-image:var(--p-fill)]","[box-shadow:var(--p-elev),var(--p-lift)]"].join(" "),glass:/* @__PURE__ */[g,"border text-(--p-accent) bg-(--p-soft)","[border-color:var(--p-line-hover)]","[box-shadow:var(--p-elev),var(--plass-gloss-glass)]"].join(" "),ghost:"text-(--p-accent) bg-(--p-soft)"},y={solid:/* @__PURE__ */["hover:brightness-105 hover:[box-shadow:var(--p-elev-hover),var(--p-lift-hover)]","active:brightness-95 active:[box-shadow:var(--p-elev-press),var(--p-lift-press)]"].join(" "),glass:"hover:bg-(--p-soft-hover) active:bg-(--p-soft-press)",ghost:"hover:bg-(--p-soft-hover) active:bg-(--p-soft-press)"};export const PlToggle=/* @__PURE__ */e.forwardRef(function PlToggle({variant:l,size:t,color:p,density:n,elevation:v,pressed:g,defaultPressed:h,onPressedChange:c,value:f,startIcon:P,endIcon:T,fullWidth:k=!1,disabled:C,className:z,style:E,children:I,onPointerMove:M,...N},B){const R=e.useContext(a),W=l??R?.variant??"glass",X=t??R?.size??"md",Y=p??R?.color??"primary",q=n??R?.density??"default",A=v??R?.elevation??0,D=C??R?.disabled??!1,F=!d(I);return s(o,{ref:B,value:f,pressed:g,defaultPressed:h,onPressedChange:s=>c?.(s),disabled:D,className:s=>[$,b[X],F?m[X]:x[q][X],D?i[W]:s.pressed?`${j[W]} ${y[W]}`:`${u[W]} ${w[W]}`,D?"":"plass-glow cursor-pointer",k?"w-full":"",z??""].filter(Boolean).join(" "),style:{...r(Y,A,W),...E},onPointerMove:s=>{const e=s.currentTarget;e.style.setProperty("--p-mx",`${s.nativeEvent.offsetX}px`),e.style.setProperty("--p-my",`${s.nativeEvent.offsetY}px`),M?.(s)},...N,children:[P,I,T]})});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassElevation, PlassOrientation, PlassStyleProps, PlassVariant } from '../../types.js';
|
|
3
|
+
export interface PlToggleGroupProps extends PlassStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'onChange'> {
|
|
4
|
+
/** Passed to every toggle in the set. @default 'glass' */
|
|
5
|
+
variant?: PlassVariant;
|
|
6
|
+
/**
|
|
7
|
+
* Which toggles are on, by their `value`. An array in both the single and the
|
|
8
|
+
* multiple case — Base UI's own shape, and the one that does not change type
|
|
9
|
+
* when `multiple` is turned on.
|
|
10
|
+
*/
|
|
11
|
+
value?: readonly string[];
|
|
12
|
+
/** Which start on, for an uncontrolled set. */
|
|
13
|
+
defaultValue?: readonly string[];
|
|
14
|
+
onValueChange?: (value: string[]) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Whether more than one can be on at a time. Off, turning one on turns the
|
|
17
|
+
* last one off — which is a one-of-a-set, and worth a second thought: if the
|
|
18
|
+
* choice is a *value* rather than a state, that is a `PlSegmentedButton` or a
|
|
19
|
+
* `PlRadioGroup`.
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
multiple?: boolean;
|
|
23
|
+
/** Which way the toggles run. @default 'horizontal' */
|
|
24
|
+
orientation?: PlassOrientation;
|
|
25
|
+
/** Drop shadow depth, passed to every toggle in the set. @default 0 */
|
|
26
|
+
elevation?: PlassElevation;
|
|
27
|
+
/** Disables every toggle in the set at once. */
|
|
28
|
+
disabled?: boolean;
|
|
29
|
+
/** Whether the arrow keys wrap around at the ends. @default true */
|
|
30
|
+
loopFocus?: boolean;
|
|
31
|
+
/** Stretches to the container and divides the width evenly between toggles. */
|
|
32
|
+
fullWidth?: boolean;
|
|
33
|
+
children?: React.ReactNode;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A set of toggles that share one state.
|
|
37
|
+
*
|
|
38
|
+
* Two things are happening and only one of them is visual. The corners facing a
|
|
39
|
+
* neighbour are squared off — that is the look. The other half is that the set
|
|
40
|
+
* owns the value: the toggles report into one array, `multiple` decides whether
|
|
41
|
+
* more than one of them can be on, and `variant`, `size`, `color`, `density`,
|
|
42
|
+
* `elevation` and `disabled` are set once here rather than on every toggle.
|
|
43
|
+
*
|
|
44
|
+
* Base UI owns the roving tab index — one tab stop for the whole set, arrow keys
|
|
45
|
+
* between the members — which is what makes a toolbar of eight toggles two key
|
|
46
|
+
* presses deep instead of eight.
|
|
47
|
+
*/
|
|
48
|
+
export declare const PlToggleGroup: React.ForwardRefExoticComponent<PlToggleGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as e}from"react/jsx-runtime";import*as o from"react";import{ToggleGroup as l}from"@base-ui/react/toggle-group";import{ButtonGroupContext as i}from"../../internal/button-group.js";import{cx as t}from"../../internal/styles.js";const n={horizontal:"[&>*:not(:first-child)]:rounded-s-none [&>*:not(:last-child)]:rounded-e-none",vertical:"[&>*:not(:first-child)]:rounded-t-none [&>*:not(:last-child)]:rounded-b-none"},r={horizontal:"[&>*:not(:first-child)]:-ms-px",vertical:"[&>*:not(:first-child)]:-mt-px"},a=/* @__PURE__ */["inline-flex align-middle","[&>*]:relative [&>*:hover]:z-10 [&>*:focus-visible]:z-10","[&>*]:shrink-0"].join(" ");export const PlToggleGroup=/* @__PURE__ */o.forwardRef(function PlToggleGroup({variant:s,size:d,color:u,density:c,elevation:f,value:m,defaultValue:h,onValueChange:p,multiple:g=!1,orientation:v="horizontal",disabled:x,loopFocus:b=!0,fullWidth:z=!1,className:j,children:V,...w},y){const G=o.useMemo(()=>({variant:s,size:d,color:u,density:c,elevation:f,disabled:x}),[s,d,u,c,f,x]);return e(i.Provider,{value:G,children:e(l,{ref:y,value:m,defaultValue:h,onValueChange:e=>p?.(e),multiple:g,orientation:v,disabled:x,loopFocus:b,className:t(a,"vertical"===v?"flex-col":"flex-row",n[v],"glass"===(s??"glass")?r[v]:"",z?"flex w-full [&>*]:flex-1":"",j),...w,children:V})})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{PlToggle}from"./PlToggle.js";export{PlToggleGroup}from"./PlToggleGroup.js";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassStyleProps } from '../../types.js';
|
|
3
|
+
/** One thing that can be on either side. */
|
|
4
|
+
export interface PlTransferItem {
|
|
5
|
+
/** What identifies it, and what `value` is a list of. */
|
|
6
|
+
value: string;
|
|
7
|
+
/** What the row says. */
|
|
8
|
+
label: React.ReactNode;
|
|
9
|
+
/** In the list but not movable. */
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface PlTransferProps extends PlassStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'onChange'> {
|
|
13
|
+
/** Everything that can be on either side, in the order the lists show it. */
|
|
14
|
+
items: readonly PlTransferItem[];
|
|
15
|
+
/** What is on the trailing side. Use with `onValueChange` for a controlled pair. */
|
|
16
|
+
value?: readonly string[];
|
|
17
|
+
/** What starts there, for an uncontrolled one. */
|
|
18
|
+
defaultValue?: readonly string[];
|
|
19
|
+
onValueChange?: (value: string[]) => void;
|
|
20
|
+
/** The heading over the leading list. @default 'Available' */
|
|
21
|
+
sourceLabel?: React.ReactNode;
|
|
22
|
+
/** And over the trailing one. @default 'Selected' */
|
|
23
|
+
targetLabel?: React.ReactNode;
|
|
24
|
+
/** Puts a filter above each list. @default false */
|
|
25
|
+
searchable?: boolean;
|
|
26
|
+
/** What that filter says while it is empty. @default 'Search' */
|
|
27
|
+
searchLabel?: string;
|
|
28
|
+
/** What a list with nothing in it says. @default 'Nothing here' */
|
|
29
|
+
emptyLabel?: string;
|
|
30
|
+
/** What the tick in a list's heading is announced as. @default 'Select all' */
|
|
31
|
+
selectAllLabel?: string;
|
|
32
|
+
/** What the two arrows are announced as. */
|
|
33
|
+
toTargetLabel?: string;
|
|
34
|
+
toSourceLabel?: string;
|
|
35
|
+
/** How tall each list is. A number of pixels or any CSS length. @default 220 */
|
|
36
|
+
height?: number | string;
|
|
37
|
+
/** Nothing can be ticked or moved. */
|
|
38
|
+
disabled?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Two lists and the arrows between them: everything that could be chosen on one
|
|
42
|
+
* side, everything that has been on the other.
|
|
43
|
+
*
|
|
44
|
+
* It is the shape for a choice that is *long* — the columns in a report, the
|
|
45
|
+
* permissions on a role, the people on a channel — where a `PlCombobox` with
|
|
46
|
+
* forty chips in its field stops being readable and a list of forty checkboxes
|
|
47
|
+
* gives no answer to "what did I actually pick". Below about a dozen options,
|
|
48
|
+
* one of those two is the smaller component.
|
|
49
|
+
*
|
|
50
|
+
* The order of `items` is the order both lists show, so a row does not move when
|
|
51
|
+
* it is sent across and back. What ticks are for is choosing which rows to move;
|
|
52
|
+
* `value` is which side they are on, and the two are deliberately separate —
|
|
53
|
+
* **ticking is not choosing**.
|
|
54
|
+
*/
|
|
55
|
+
export declare const PlTransfer: React.ForwardRefExoticComponent<PlTransferProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as e,jsxs as l}from"react/jsx-runtime";import*as a from"react";import{PlCheckbox as t}from"../checkbox/PlCheckbox.js";import{PlIconButton as s}from"../icon-button/PlIconButton.js";import{PlTextField as r}from"../text-field/PlTextField.js";import{ArrowRightIcon as i}from"../../internal/icons.js";import{searchText as n}from"../../internal/search.js";import{cx as o,fieldRestClasses as c,hasContent as d,metaTextClasses as h,paddingXClasses as m,radiusClasses as u,surfaceSlots as b,toLength as f}from"../../internal/styles.js";const v={xs:"py-1",sm:"py-1.5",md:"py-2",lg:"py-2.5",xl:"py-3"},p={xs:"py-0.5",sm:"py-1",md:"py-1",lg:"py-1.5",xl:"py-2"};function Panel({title:a,rows:s,ticked:i,onTick:n,onTickAll:d,search:f,onSearch:g,searchable:y,disabled:x,height:k,emptyLabel:w,searchLabel:S,selectAllLabel:L,style:N}){const{variant:T,size:j,color:A,density:C}=N,z=s.filter(e=>!e.disabled),P=z.filter(e=>i.has(e.value)),M=z.length>0&&P.length===z.length,V=P.length>0&&!M,_=m[C][j];return l("div",{className:o("flex min-w-0 flex-col overflow-hidden",c[T],u[j]),style:b(A,0),children:[l("div",{className:o("flex items-center gap-2 border-b [border-color:var(--plass-divider)]",_,v[j]),children:[e(t,{size:j,color:A,checked:M,indeterminate:V,disabled:x||0===z.length,"aria-label":L,onCheckedChange:e=>d(!0===e)}),e("span",{className:o("min-w-0 flex-1 truncate font-medium",h[j]),children:a}),l("span",{className:o("shrink-0 tabular-nums text-(--plass-muted-fg)",h[j]),children:[P.length,"/",s.length]})]}),y?e("div",{className:o(_,v[j]),children:e(r,{size:j,color:A,density:C,fullWidth:!0,variant:"ghost",disabled:x,placeholder:S,"aria-label":S,value:f,onChange:e=>g(e.target.value)})}):null,e("div",{className:"min-h-0 flex-1 overflow-y-auto overscroll-contain",style:void 0===k?void 0:{height:k},children:e("div",{className:o("flex flex-col",_,v[j]),children:0===s.length?e("span",{className:o("text-(--plass-muted-fg)",h[j],p[j]),children:w}):s.map(l=>e(t,{size:j,color:A,className:p[j],label:l.label,checked:i.has(l.value),disabled:x||l.disabled,onCheckedChange:e=>n(l.value,!0===e)},l.value))})})]})}function narrow(e,l){const a=n(l);return""===a?e:e.filter(e=>"string"!=typeof e.label||n(e.label).includes(a))}export const PlTransfer=/* @__PURE__ */a.forwardRef(function PlTransfer({items:t,value:r,defaultValue:n,onValueChange:c,sourceLabel:h="Available",targetLabel:m="Selected",searchable:u=!1,searchLabel:b="Search",emptyLabel:v="Nothing here",selectAllLabel:p="Select all",toTargetLabel:g="Move to selected",toSourceLabel:y="Move to available",height:x=220,disabled:k=!1,variant:w="glass",size:S="md",color:L="primary",density:N="default",className:T,...j},A){const[C,z]=a.useState(n??[]),P=r??C,[M,V]=a.useState(()=>new Set),[_,B]=a.useState(""),[F,I]=a.useState(""),R=a.useMemo(()=>new Set(P),[P]),W=a.useMemo(()=>t.filter(e=>!R.has(e.value)),[t,R]),q=a.useMemo(()=>t.filter(e=>R.has(e.value)),[t,R]),tick=(e,l)=>{V(a=>{const t=new Set(a);return l?t.add(e):t.delete(e),t})},tickAll=(e,l)=>{V(a=>{const t=new Set(a);for(const a of e)a.disabled||(l?t.add(a.value):t.delete(a.value));return t})},move=(e,l)=>{const a=e.filter(e=>!e.disabled&&M.has(e.value));if(0===a.length)return;const s=new Set(a.map(e=>e.value)),i=l?t.filter(e=>R.has(e.value)||s.has(e.value)).map(e=>e.value):P.filter(e=>!s.has(e));V(e=>new Set([...e].filter(e=>!s.has(e)))),(e=>{void 0===r&&z(e),c?.(e)})(i)},D=narrow(W,_),E=narrow(q,F),G=D.some(e=>!e.disabled&&M.has(e.value)),H=E.some(e=>!e.disabled&&M.has(e.value)),J=f(x),K={variant:w,size:S,color:L,density:N},O="ghost"===w?"ghost":"glass";return l("div",{ref:A,className:o("grid w-full items-center gap-3","[grid-template-columns:minmax(0,1fr)_auto_minmax(0,1fr)]",T),...j,children:[e(Panel,{title:d(h)?h:"Available",rows:D,ticked:M,onTick:tick,onTickAll:e=>tickAll(D,e),search:_,onSearch:B,searchable:u,disabled:k,height:J,emptyLabel:v,searchLabel:b,selectAllLabel:p,style:K}),l("div",{className:"flex flex-col gap-2",children:[e(s,{size:S,color:L,variant:O,label:g,disabled:k||!G,onClick:()=>move(D,!0),icon:e(i,{})}),e(s,{size:S,color:L,variant:O,label:y,disabled:k||!H,onClick:()=>move(E,!1),icon:e("span",{className:"flex rotate-180",children:e(i,{})})})]}),e(Panel,{title:d(m)?m:"Selected",rows:E,ticked:M,onTick:tick,onTickAll:e=>tickAll(E,e),search:F,onSearch:I,searchable:u,disabled:k,height:J,emptyLabel:v,searchLabel:b,selectAllLabel:p,style:K})]})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{PlTransfer}from"./PlTransfer.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export * from './components/animate-typing/index.js';
|
|
|
14
14
|
export * from './components/animate-zoom/index.js';
|
|
15
15
|
export * from './components/aspect-ratio/index.js';
|
|
16
16
|
export * from './components/avatar/index.js';
|
|
17
|
+
export * from './components/avatar-group/index.js';
|
|
17
18
|
export * from './components/badge/index.js';
|
|
18
19
|
export * from './components/blockquote/index.js';
|
|
19
20
|
export * from './components/bottom-navigation/index.js';
|
|
@@ -27,26 +28,35 @@ export * from './components/chat-bubble/index.js';
|
|
|
27
28
|
export * from './components/checkbox/index.js';
|
|
28
29
|
export * from './components/chip/index.js';
|
|
29
30
|
export * from './components/collapsible/index.js';
|
|
31
|
+
export * from './components/color-picker/index.js';
|
|
30
32
|
export * from './components/combobox/index.js';
|
|
33
|
+
export * from './components/command-palette/index.js';
|
|
31
34
|
export * from './components/container/index.js';
|
|
32
35
|
export * from './components/date-picker/index.js';
|
|
33
36
|
export * from './components/date-range-picker/index.js';
|
|
34
37
|
export * from './components/date-time-picker/index.js';
|
|
35
38
|
export * from './components/divider/index.js';
|
|
36
39
|
export * from './components/drawer/index.js';
|
|
40
|
+
export * from './components/fieldset/index.js';
|
|
37
41
|
export * from './components/file-picker/index.js';
|
|
38
42
|
export * from './components/floating-bottom-navigation/index.js';
|
|
43
|
+
export * from './components/footer/index.js';
|
|
44
|
+
export * from './components/form/index.js';
|
|
39
45
|
export * from './components/grid/index.js';
|
|
46
|
+
export * from './components/header/index.js';
|
|
40
47
|
export * from './components/highlight/index.js';
|
|
41
48
|
export * from './components/hot-keys/index.js';
|
|
42
49
|
export * from './components/icon/index.js';
|
|
43
50
|
export * from './components/icon-button/index.js';
|
|
44
51
|
export * from './components/list/index.js';
|
|
45
52
|
export * from './components/menu/index.js';
|
|
53
|
+
export * from './components/menubar/index.js';
|
|
46
54
|
export * from './components/modal/index.js';
|
|
55
|
+
export * from './components/navigation-menu/index.js';
|
|
47
56
|
export * from './components/number-field/index.js';
|
|
48
57
|
export * from './components/otp-field/index.js';
|
|
49
58
|
export * from './components/overlay/index.js';
|
|
59
|
+
export * from './components/page-layout/index.js';
|
|
50
60
|
export * from './components/pagination/index.js';
|
|
51
61
|
export * from './components/panes/index.js';
|
|
52
62
|
export * from './components/pill/index.js';
|
|
@@ -59,6 +69,7 @@ export * from './components/rating/index.js';
|
|
|
59
69
|
export * from './components/scroll-zone/index.js';
|
|
60
70
|
export * from './components/segmented-button/index.js';
|
|
61
71
|
export * from './components/select/index.js';
|
|
72
|
+
export * from './components/sidebar/index.js';
|
|
62
73
|
export * from './components/skeleton/index.js';
|
|
63
74
|
export * from './components/slider/index.js';
|
|
64
75
|
export * from './components/spoiler/index.js';
|
|
@@ -70,6 +81,8 @@ export * from './components/text-link/index.js';
|
|
|
70
81
|
export * from './components/time-picker/index.js';
|
|
71
82
|
export * from './components/timeline/index.js';
|
|
72
83
|
export * from './components/toast/index.js';
|
|
84
|
+
export * from './components/toggle/index.js';
|
|
73
85
|
export * from './components/toolbar/index.js';
|
|
74
86
|
export * from './components/tooltip/index.js';
|
|
87
|
+
export * from './components/transfer/index.js';
|
|
75
88
|
export * from './components/typography/index.js';
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export*from"./types.js";export*from"./components/accordion/index.js";export*from"./components/alert/index.js";export*from"./components/animate-appear/index.js";export*from"./components/animate-blink/index.js";export*from"./components/animate-fade/index.js";export*from"./components/animate-grow/index.js";export*from"./components/animate-headline/index.js";export*from"./components/animate-lighting/index.js";export*from"./components/animate-marquee/index.js";export*from"./components/animate-rotate/index.js";export*from"./components/animate-slide/index.js";export*from"./components/animate-typing/index.js";export*from"./components/animate-zoom/index.js";export*from"./components/aspect-ratio/index.js";export*from"./components/avatar/index.js";export*from"./components/badge/index.js";export*from"./components/blockquote/index.js";export*from"./components/bottom-navigation/index.js";export*from"./components/box/index.js";export*from"./components/breadcrumb/index.js";export*from"./components/button/index.js";export*from"./components/button-group/index.js";export*from"./components/card/index.js";export*from"./components/carousel/index.js";export*from"./components/chat-bubble/index.js";export*from"./components/checkbox/index.js";export*from"./components/chip/index.js";export*from"./components/collapsible/index.js";export*from"./components/combobox/index.js";export*from"./components/container/index.js";export*from"./components/date-picker/index.js";export*from"./components/date-range-picker/index.js";export*from"./components/date-time-picker/index.js";export*from"./components/divider/index.js";export*from"./components/drawer/index.js";export*from"./components/file-picker/index.js";export*from"./components/floating-bottom-navigation/index.js";export*from"./components/grid/index.js";export*from"./components/highlight/index.js";export*from"./components/hot-keys/index.js";export*from"./components/icon/index.js";export*from"./components/icon-button/index.js";export*from"./components/list/index.js";export*from"./components/menu/index.js";export*from"./components/modal/index.js";export*from"./components/number-field/index.js";export*from"./components/otp-field/index.js";export*from"./components/overlay/index.js";export*from"./components/pagination/index.js";export*from"./components/panes/index.js";export*from"./components/pill/index.js";export*from"./components/popover/index.js";export*from"./components/progress-box/index.js";export*from"./components/progress-circular/index.js";export*from"./components/progress-linear/index.js";export*from"./components/radio-group/index.js";export*from"./components/rating/index.js";export*from"./components/scroll-zone/index.js";export*from"./components/segmented-button/index.js";export*from"./components/select/index.js";export*from"./components/skeleton/index.js";export*from"./components/slider/index.js";export*from"./components/spoiler/index.js";export*from"./components/switch/index.js";export*from"./components/table/index.js";export*from"./components/tabs/index.js";export*from"./components/text-field/index.js";export*from"./components/text-link/index.js";export*from"./components/time-picker/index.js";export*from"./components/timeline/index.js";export*from"./components/toast/index.js";export*from"./components/toolbar/index.js";export*from"./components/tooltip/index.js";export*from"./components/typography/index.js";
|
|
1
|
+
export*from"./types.js";export*from"./components/accordion/index.js";export*from"./components/alert/index.js";export*from"./components/animate-appear/index.js";export*from"./components/animate-blink/index.js";export*from"./components/animate-fade/index.js";export*from"./components/animate-grow/index.js";export*from"./components/animate-headline/index.js";export*from"./components/animate-lighting/index.js";export*from"./components/animate-marquee/index.js";export*from"./components/animate-rotate/index.js";export*from"./components/animate-slide/index.js";export*from"./components/animate-typing/index.js";export*from"./components/animate-zoom/index.js";export*from"./components/aspect-ratio/index.js";export*from"./components/avatar/index.js";export*from"./components/avatar-group/index.js";export*from"./components/badge/index.js";export*from"./components/blockquote/index.js";export*from"./components/bottom-navigation/index.js";export*from"./components/box/index.js";export*from"./components/breadcrumb/index.js";export*from"./components/button/index.js";export*from"./components/button-group/index.js";export*from"./components/card/index.js";export*from"./components/carousel/index.js";export*from"./components/chat-bubble/index.js";export*from"./components/checkbox/index.js";export*from"./components/chip/index.js";export*from"./components/collapsible/index.js";export*from"./components/color-picker/index.js";export*from"./components/combobox/index.js";export*from"./components/command-palette/index.js";export*from"./components/container/index.js";export*from"./components/date-picker/index.js";export*from"./components/date-range-picker/index.js";export*from"./components/date-time-picker/index.js";export*from"./components/divider/index.js";export*from"./components/drawer/index.js";export*from"./components/fieldset/index.js";export*from"./components/file-picker/index.js";export*from"./components/floating-bottom-navigation/index.js";export*from"./components/footer/index.js";export*from"./components/form/index.js";export*from"./components/grid/index.js";export*from"./components/header/index.js";export*from"./components/highlight/index.js";export*from"./components/hot-keys/index.js";export*from"./components/icon/index.js";export*from"./components/icon-button/index.js";export*from"./components/list/index.js";export*from"./components/menu/index.js";export*from"./components/menubar/index.js";export*from"./components/modal/index.js";export*from"./components/navigation-menu/index.js";export*from"./components/number-field/index.js";export*from"./components/otp-field/index.js";export*from"./components/overlay/index.js";export*from"./components/page-layout/index.js";export*from"./components/pagination/index.js";export*from"./components/panes/index.js";export*from"./components/pill/index.js";export*from"./components/popover/index.js";export*from"./components/progress-box/index.js";export*from"./components/progress-circular/index.js";export*from"./components/progress-linear/index.js";export*from"./components/radio-group/index.js";export*from"./components/rating/index.js";export*from"./components/scroll-zone/index.js";export*from"./components/segmented-button/index.js";export*from"./components/select/index.js";export*from"./components/sidebar/index.js";export*from"./components/skeleton/index.js";export*from"./components/slider/index.js";export*from"./components/spoiler/index.js";export*from"./components/switch/index.js";export*from"./components/table/index.js";export*from"./components/tabs/index.js";export*from"./components/text-field/index.js";export*from"./components/text-link/index.js";export*from"./components/time-picker/index.js";export*from"./components/timeline/index.js";export*from"./components/toast/index.js";export*from"./components/toggle/index.js";export*from"./components/toolbar/index.js";export*from"./components/tooltip/index.js";export*from"./components/transfer/index.js";export*from"./components/typography/index.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a `PlAvatar` inherits from the `PlAvatarGroup` around it.
|
|
3
|
+
*
|
|
4
|
+
* `button-group.ts`'s arrangement, one component over and for the same two
|
|
5
|
+
* reasons. Cloning the children with `React.cloneElement` stops working the
|
|
6
|
+
* moment a caller wraps one of them in a `PlTooltip`, a `<Fragment>` or a
|
|
7
|
+
* `.map()` — which is most of the time — and a context reaches the avatar
|
|
8
|
+
* wherever it ended up. And it lives here rather than beside the group so that
|
|
9
|
+
* `PlAvatar` can read it without the two components importing each other.
|
|
10
|
+
*
|
|
11
|
+
* Every field is optional, and every one of them means *not specified* rather
|
|
12
|
+
* than a value: an avatar falls back to its own default, so a group with no
|
|
13
|
+
* props of its own changes nothing except the overlap.
|
|
14
|
+
*/
|
|
15
|
+
import * as React from 'react';
|
|
16
|
+
import type { PlAvatarShape } from '../components/avatar/PlAvatar.js';
|
|
17
|
+
import type { PlassColor, PlassElevation, PlassSize, PlassVariant } from '../types.js';
|
|
18
|
+
export interface PlassAvatarGroupContextValue {
|
|
19
|
+
size?: PlassSize;
|
|
20
|
+
shape?: PlAvatarShape;
|
|
21
|
+
variant?: PlassVariant;
|
|
22
|
+
color?: PlassColor;
|
|
23
|
+
elevation?: PlassElevation;
|
|
24
|
+
}
|
|
25
|
+
export declare const AvatarGroupContext: React.Context<PlassAvatarGroupContextValue | null>;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Colour arithmetic, written out rather than installed.
|
|
3
|
+
*
|
|
4
|
+
* `PlColorPicker` is the only component that has to *compute* a colour rather
|
|
5
|
+
* than name one, and the whole of what it needs is here: three representations,
|
|
6
|
+
* the conversions between them, one parser and one formatter. It is a hundred
|
|
7
|
+
* lines of trigonometry-free arithmetic, which is the entire reason a component
|
|
8
|
+
* that computes colours brings no colour library with it.
|
|
9
|
+
*
|
|
10
|
+
* Two decisions worth knowing before reading:
|
|
11
|
+
*
|
|
12
|
+
* - **HSV is the model the panel is drawn in, and it never leaves.** A
|
|
13
|
+
* saturation/value square with a hue rail beside it *is* HSV, so the picker
|
|
14
|
+
* keeps its state that way and converts on the way out. Round-tripping
|
|
15
|
+
* through RGB instead would lose the hue of every greyscale colour — black is
|
|
16
|
+
* `#000` at every hue — and the rail would jump to red the moment the pointer
|
|
17
|
+
* reached a corner.
|
|
18
|
+
* - **`alpha` is 0–1, everything else is what CSS says it is.** `h` is degrees,
|
|
19
|
+
* `s`/`v`/`l` are percentages, `r`/`g`/`b` are 0–255. Nothing here invents a
|
|
20
|
+
* normalised unit, because every one of these numbers is eventually written
|
|
21
|
+
* into a string a human reads.
|
|
22
|
+
*
|
|
23
|
+
* Nothing here is exported from `src/index.ts` except the two types the picker's
|
|
24
|
+
* own props need. It is the library talking to itself, in the sense that
|
|
25
|
+
* `internal/` always means.
|
|
26
|
+
*/
|
|
27
|
+
/** 0–255 per channel, the way a hex triplet and `rgb()` both spell it. */
|
|
28
|
+
export interface PlassRgb {
|
|
29
|
+
r: number;
|
|
30
|
+
g: number;
|
|
31
|
+
b: number;
|
|
32
|
+
}
|
|
33
|
+
/** `h` in degrees, `s` and `v` as percentages. The panel's own model. */
|
|
34
|
+
export interface PlassHsv {
|
|
35
|
+
h: number;
|
|
36
|
+
s: number;
|
|
37
|
+
v: number;
|
|
38
|
+
}
|
|
39
|
+
/** `h` in degrees, `s` and `l` as percentages. Only ever an output format. */
|
|
40
|
+
export interface PlassHsl {
|
|
41
|
+
h: number;
|
|
42
|
+
s: number;
|
|
43
|
+
l: number;
|
|
44
|
+
}
|
|
45
|
+
/** A colour and how much of it there is. `alpha` is 0–1. */
|
|
46
|
+
export interface PlassColorValue {
|
|
47
|
+
hsv: PlassHsv;
|
|
48
|
+
alpha: number;
|
|
49
|
+
}
|
|
50
|
+
/** The three ways the picker will write a colour back out. */
|
|
51
|
+
export type PlColorFormat = 'hex' | 'rgb' | 'hsl';
|
|
52
|
+
export declare function clamp(value: number, min: number, max: number): number;
|
|
53
|
+
export declare function hsvToRgb({ h, s, v }: PlassHsv): PlassRgb;
|
|
54
|
+
export declare function rgbToHsv({ r, g, b }: PlassRgb): PlassHsv;
|
|
55
|
+
export declare function rgbToHsl({ r, g, b }: PlassRgb): PlassHsl;
|
|
56
|
+
export declare function hslToRgb({ h, s, l }: PlassHsl): PlassRgb;
|
|
57
|
+
/**
|
|
58
|
+
* A CSS colour string, or `null` if it is not one this understands.
|
|
59
|
+
*
|
|
60
|
+
* Hex in all four lengths, `rgb()`/`rgba()` and `hsl()`/`hsla()` in both the
|
|
61
|
+
* comma and the space syntax. Named colours and `color()` are deliberately out:
|
|
62
|
+
* a picker has to be able to write every value it can read, and there is no
|
|
63
|
+
* honest way back from `rebeccapurple` to a point on the panel.
|
|
64
|
+
*/
|
|
65
|
+
export declare function parseColor(input: string): PlassColorValue | null;
|
|
66
|
+
export declare function rgbToHex({ r, g, b }: PlassRgb, alpha?: number): string;
|
|
67
|
+
/**
|
|
68
|
+
* The value the component hands back, in whichever notation was asked for.
|
|
69
|
+
*
|
|
70
|
+
* `hex` drops the alpha pair when the colour is opaque, and the two functional
|
|
71
|
+
* forms drop the fourth argument for the same reason — a caller who never
|
|
72
|
+
* turned `alpha` on should never see `rgba(…, 1)` come out of a control they
|
|
73
|
+
* only used three channels of.
|
|
74
|
+
*/
|
|
75
|
+
export declare function formatColor(hsv: PlassHsv, alpha: number, format: PlColorFormat): string;
|
|
76
|
+
/** A plain `rgb()` for the swatches and rails, where alpha is drawn separately. */
|
|
77
|
+
export declare function cssColor(hsv: PlassHsv, alpha?: number): string;
|
|
78
|
+
/**
|
|
79
|
+
* Black or white, whichever can be read on top of this colour.
|
|
80
|
+
*
|
|
81
|
+
* The tick on a chosen swatch is the only thing the picker draws *on* an
|
|
82
|
+
* arbitrary colour, and a fixed white tick disappears on yellow. The threshold
|
|
83
|
+
* is relative luminance rather than plain lightness, because the eye weighs
|
|
84
|
+
* green about six times as heavily as blue and a colour model that pretends
|
|
85
|
+
* otherwise puts the tick the wrong way round on both.
|
|
86
|
+
*/
|
|
87
|
+
export declare function readableInk(hsv: PlassHsv): string;
|
|
88
|
+
/**
|
|
89
|
+
* The swatches a picker shows when it was given none.
|
|
90
|
+
*
|
|
91
|
+
* Deliberately **not** the library's own six families: those are semantic roles
|
|
92
|
+
* and a picker is asked for a colour, not for a meaning. This is a plain
|
|
93
|
+
* spectrum plus the greys — the row somebody reaches for when they are
|
|
94
|
+
* labelling a calendar, a tag or a project, which is what a colour picker in an
|
|
95
|
+
* application is nearly always for.
|
|
96
|
+
*/
|
|
97
|
+
export declare const defaultSwatches: readonly string[];
|
|
98
|
+
/**
|
|
99
|
+
* The chequerboard behind a translucent colour, as a background shorthand.
|
|
100
|
+
*
|
|
101
|
+
* Two conic gradients would be one declaration fewer, but a chequer drawn with
|
|
102
|
+
* conic gradients has a seam down the middle of every tile on a fractional
|
|
103
|
+
* device pixel ratio. Four linear stops at 45° do not.
|
|
104
|
+
*/
|
|
105
|
+
export declare const checkerBackground: {
|
|
106
|
+
readonly backgroundImage: "linear-gradient(45deg, var(--plass-border) 25%, transparent 25%), linear-gradient(-45deg, var(--plass-border) 25%, transparent 25%), linear-gradient(45deg, transparent 75%, var(--plass-border) 75%), linear-gradient(-45deg, transparent 75%, var(--plass-border) 75%)";
|
|
107
|
+
readonly backgroundSize: "8px 8px";
|
|
108
|
+
readonly backgroundPosition: "0 0, 0 4px, 4px -4px, -4px 0";
|
|
109
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function clamp(r,n,t){return r<n?n:r>t?t:r}function wrapHue(r){const n=r%360;return n<0?n+360:n}function round(r){return Math.round(r)}export function hsvToRgb({h:r,s:n,v:t}){const e=wrapHue(r)/60,o=clamp(n,0,100)/100,a=clamp(t,0,100)/100,s=a*o,u=s*(1-Math.abs(e%2-1)),c=a-s,l=Math.floor(e)%6,[g,h,i]=[[s,u,0],[u,s,0],[0,s,u],[0,u,s],[u,0,s],[s,0,u]][l];return{r:round(255*(g+c)),g:round(255*(h+c)),b:round(255*(i+c))}}export function rgbToHsv({r,g:n,b:t}){const e=clamp(r,0,255)/255,o=clamp(n,0,255)/255,a=clamp(t,0,255)/255,s=Math.max(e,o,a),u=s-Math.min(e,o,a);let c=0;return 0!==u&&(c=s===e?(o-a)/u%6:s===o?(a-e)/u+2:(e-o)/u+4),{h:wrapHue(60*c),s:0===s?0:u/s*100,v:100*s}}export function rgbToHsl({r,g:n,b:t}){const{h:e,s:o,v:a}=rgbToHsv({r,g:n,b:t}),s=a/100,u=s*(1-o/100/2),c=Math.min(u,1-u);return{h:e,s:0===c?0:(s-u)/c*100,l:100*u}}export function hslToRgb({h:r,s:n,l:t}){const e=clamp(t,0,100)/100,o=e+clamp(n,0,100)/100*Math.min(e,1-e);return hsvToRgb({h:r,s:0===o?0:2*(1-e/o)*100,v:100*o})}const r=/^#?([0-9a-f]{3,8})$/i;export function parseColor(n){const t=n.trim().toLowerCase();if(!t)return null;if(t.startsWith("#")||r.test(t))return function hexToRgba(n){const t=r.exec(n.trim());if(!t)return null;const e=t[1],o=3===e.length||4===e.length?[...e].map(r=>r+r).join(""):e;if(6!==o.length&&8!==o.length)return null;const channel=r=>parseInt(o.slice(2*r,2*r+2),16);return{hsv:rgbToHsv({r:channel(0),g:channel(1),b:channel(2)}),alpha:8===o.length?channel(3)/255:1}}(t);const e=/^(rgba?|hsla?)\((.*)\)$/.exec(t);if(!e)return null;const[,o,a]=e,s=function numbersIn(r){return(r.match(/-?[\d.]+%?/g)??[]).map(r=>parseFloat(r))}(a);if(s.length<3||s.some(Number.isNaN))return null;const u=function alphaOf(r,n,t){if(n.length<=t)return 1;const e=r.match(/-?[\d.]+%?/g)??[];return clamp(e[t]?.endsWith("%")?n[t]/100:n[t],0,1)}(a,s,3);return o.startsWith("rgb")?{hsv:rgbToHsv({r:s[0],g:s[1],b:s[2]}),alpha:u}:{hsv:rgbToHsv(hslToRgb({h:s[0],s:s[1],l:s[2]})),alpha:u}}function hexPair(r){return clamp(round(r),0,255).toString(16).padStart(2,"0")}export function rgbToHex({r,g:n,b:t},e=1){const o=`#${hexPair(r)}${hexPair(n)}${hexPair(t)}`;return e>=1?o:`${o}${hexPair(255*e)}`}function alphaText(r){return String(Math.round(100*clamp(r,0,1))/100)}export function formatColor(r,n,t){const e=hsvToRgb(r);if("hex"===t)return rgbToHex(e,n);if("rgb"===t){const r=`${round(e.r)}, ${round(e.g)}, ${round(e.b)}`;return n>=1?`rgb(${r})`:`rgba(${r}, ${alphaText(n)})`}const{h:o,s:a,l:s}=rgbToHsl(e),u=`${round(o)}, ${round(a)}%, ${round(s)}%`;return n>=1?`hsl(${u})`:`hsla(${u}, ${alphaText(n)})`}export function cssColor(r,n=1){const{r:t,g:e,b:o}=hsvToRgb(r);return n>=1?`rgb(${t}, ${e}, ${o})`:`rgba(${t}, ${e}, ${o}, ${alphaText(n)})`}export function readableInk(r){const{r:n,g:t,b:e}=hsvToRgb(r),channel=r=>{const n=r/255;return n<=.03928?n/12.92:((n+.055)/1.055)**2.4};return.2126*channel(n)+.7152*channel(t)+.0722*channel(e)>.42?"#000000":"#ffffff"}export const defaultSwatches=["#000000","#4b5563","#9ca3af","#ffffff","#ef4444","#f97316","#f59e0b","#84cc16","#22c55e","#14b8a6","#06b6d4","#3b82f6","#6366f1","#8b5cf6","#d946ef","#ec4899"];export const checkerBackground={backgroundImage:"linear-gradient(45deg, var(--plass-border) 25%, transparent 25%), linear-gradient(-45deg, var(--plass-border) 25%, transparent 25%), linear-gradient(45deg, transparent 75%, var(--plass-border) 75%), linear-gradient(-45deg, transparent 75%, var(--plass-border) 75%)",backgroundSize:"8px 8px",backgroundPosition:"0 0, 0 4px, 4px -4px, -4px 0"};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one thing a `rel` must not lose.
|
|
3
|
+
*
|
|
4
|
+
* `noopener` is what stops a page opened in a new tab reaching back through
|
|
5
|
+
* `window.opener`; `noreferrer` sits beside it for the browsers that still need
|
|
6
|
+
* the pair. The common reason to write a `rel` by hand is `nofollow` or
|
|
7
|
+
* `sponsored`, which is an SEO decision — and spelled as a plain override it
|
|
8
|
+
* would silently take the protection off a link that still opens elsewhere.
|
|
9
|
+
*
|
|
10
|
+
* So the caller's value is **merged** rather than replaced: whatever was asked
|
|
11
|
+
* for is kept, with the two tokens added if they are not already there, and a
|
|
12
|
+
* link that stays in this tab keeps exactly the `rel` it was given.
|
|
13
|
+
*
|
|
14
|
+
* Here rather than in either component that needs it — `PlTextLink` and
|
|
15
|
+
* `PlNavigationMenu` — because two copies of a security default are two copies
|
|
16
|
+
* that can drift, and the one that drifts is the one nobody reads.
|
|
17
|
+
*/
|
|
18
|
+
export declare function safeRel(target: string | undefined, rel: string | undefined): string | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function safeRel(e,n){return void 0===e||""===e||"_self"===e?n:[...new Set([...(n??"").split(/\s+/).filter(Boolean),"noopener","noreferrer"])].join(" ")}
|