@parallelworks/ui 0.59.0 → 0.60.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/dist/components/ColorInput.d.ts +3 -1
- package/dist/components/ColorInput.js +2 -1
- package/dist/components/Input.d.ts +3 -1
- package/dist/components/Input.js +2 -1
- package/dist/components/Provider.d.ts +2 -0
- package/dist/components/Provider.js +1 -0
- package/dist/components/ThemeEditor.js +10 -0
- package/dist/theme/derive.js +12 -7
- package/package.json +1 -1
|
@@ -9,6 +9,8 @@ export interface ColorInputProps {
|
|
|
9
9
|
label?: ReactNode;
|
|
10
10
|
/** Beside the label and outside it, so it stays out of the field's name. */
|
|
11
11
|
hint?: ReactNode;
|
|
12
|
+
/** Buttons at the far end of the label's row that act on the color, as Field's `actions`. */
|
|
13
|
+
actions?: ReactNode;
|
|
12
14
|
/** Help under the field. */
|
|
13
15
|
description?: ReactNode;
|
|
14
16
|
error?: ReactNode;
|
|
@@ -33,4 +35,4 @@ export interface ColorInputProps {
|
|
|
33
35
|
* in. A half-typed color stays in the field, marked invalid, until it parses; leaving the field
|
|
34
36
|
* puts back the last color that did.
|
|
35
37
|
*/
|
|
36
|
-
export declare function ColorInput({ value, onValueChange, label, hint, description, error, size, id, name, disabled, required, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, 'aria-invalid': ariaInvalid, 'aria-required': ariaRequired, className, }: ColorInputProps): string | number | bigint | boolean | import("react").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | Iterable<ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null | undefined;
|
|
38
|
+
export declare function ColorInput({ value, onValueChange, label, hint, actions, description, error, size, id, name, disabled, required, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, 'aria-invalid': ariaInvalid, 'aria-required': ariaRequired, className, }: ColorInputProps): string | number | bigint | boolean | import("react").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | Iterable<ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null | undefined;
|
|
@@ -14,7 +14,7 @@ var swatchClassName = cx("shrink-0 cursor-pointer p-0.5", "[&::-webkit-color-swa
|
|
|
14
14
|
* in. A half-typed color stays in the field, marked invalid, until it parses; leaving the field
|
|
15
15
|
* puts back the last color that did.
|
|
16
16
|
*/
|
|
17
|
-
function ColorInput({ value, onValueChange, label, hint, description, error, size = "md", id, name, disabled, required, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, "aria-required": ariaRequired, className }) {
|
|
17
|
+
function ColorInput({ value, onValueChange, label, hint, actions, description, error, size = "md", id, name, disabled, required, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, "aria-required": ariaRequired, className }) {
|
|
18
18
|
const t = useStrings().colorInput;
|
|
19
19
|
const [draft, setDraft] = useState(null);
|
|
20
20
|
const errorId = useId();
|
|
@@ -25,6 +25,7 @@ function ColorInput({ value, onValueChange, label, hint, description, error, siz
|
|
|
25
25
|
return framed({
|
|
26
26
|
label,
|
|
27
27
|
hint,
|
|
28
|
+
actions,
|
|
28
29
|
description,
|
|
29
30
|
error: error ?? (unparsed ? t.invalid : void 0),
|
|
30
31
|
size
|
|
@@ -22,7 +22,9 @@ export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElemen
|
|
|
22
22
|
ref?: Ref<HTMLTextAreaElement> | undefined;
|
|
23
23
|
}
|
|
24
24
|
/** The Field around a control when it has a label; the control alone when it doesn't. */
|
|
25
|
-
export declare function framed({ label, hint, help, description, error, size }: Omit<FramedProps, 'mono'
|
|
25
|
+
export declare function framed({ label, hint, help, actions, description, error, size, }: Omit<FramedProps, 'mono'> & {
|
|
26
|
+
actions?: ReactNode;
|
|
27
|
+
}, { id, required, disabled, }: {
|
|
26
28
|
id?: string | undefined;
|
|
27
29
|
required?: boolean | undefined;
|
|
28
30
|
disabled?: boolean | undefined;
|
package/dist/components/Input.js
CHANGED
|
@@ -6,12 +6,13 @@ import { useState } from "react";
|
|
|
6
6
|
import { Input } from "@base-ui/react/input";
|
|
7
7
|
//#region src/components/Input.tsx
|
|
8
8
|
/** The Field around a control when it has a label; the control alone when it doesn't. */
|
|
9
|
-
function framed({ label, hint, help, description, error, size }, { id, required, disabled }, control) {
|
|
9
|
+
function framed({ label, hint, help, actions, description, error, size }, { id, required, disabled }, control) {
|
|
10
10
|
if (label === void 0) return control(error ? { "aria-invalid": true } : {});
|
|
11
11
|
return /* @__PURE__ */ jsx(Field, {
|
|
12
12
|
label,
|
|
13
13
|
hint,
|
|
14
14
|
help,
|
|
15
|
+
actions,
|
|
15
16
|
description,
|
|
16
17
|
error,
|
|
17
18
|
required,
|
|
@@ -153,6 +153,8 @@ export interface UIStrings {
|
|
|
153
153
|
/** The background a theme is generated from. */
|
|
154
154
|
base: string;
|
|
155
155
|
accent: string;
|
|
156
|
+
/** Exchanges the background and the accent. */
|
|
157
|
+
swap: string;
|
|
156
158
|
contrast: string;
|
|
157
159
|
/** Under the contrast slider. */
|
|
158
160
|
contrastHelp: string;
|
|
@@ -153,6 +153,7 @@ var DEFAULTS = {
|
|
|
153
153
|
presets: "Presets",
|
|
154
154
|
base: "Background",
|
|
155
155
|
accent: "Accent",
|
|
156
|
+
swap: "Swap background and accent",
|
|
156
157
|
contrast: "Contrast",
|
|
157
158
|
contrastHelp: "Separates surfaces and strengthens text. Text always meets WCAG AA.",
|
|
158
159
|
customSidebar: "Custom sidebar",
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { cx } from "../cx.js";
|
|
2
|
+
import { SwapIcon } from "../icons.js";
|
|
2
3
|
import { useStrings } from "./Provider.js";
|
|
3
4
|
import { useCopy } from "./useCopy.js";
|
|
4
5
|
import { Button } from "./Button.js";
|
|
6
|
+
import { IconButton } from "./IconButton.js";
|
|
5
7
|
import { fieldBox } from "./fieldBox.js";
|
|
6
8
|
import { parseColor, toHex } from "../theme/color.js";
|
|
7
9
|
import { CODE_STYLES, DEFAULT_THEME, THEME_PRESETS, modeOf, parseTheme, schemeFor, serializeTheme } from "../theme/model.js";
|
|
@@ -110,6 +112,14 @@ function ThemeEditor({ value, onChange, mode, onModeChange, preference, onPrefer
|
|
|
110
112
|
}),
|
|
111
113
|
/* @__PURE__ */ jsx(ColorInput, {
|
|
112
114
|
label: t.accent,
|
|
115
|
+
actions: /* @__PURE__ */ jsx(IconButton, {
|
|
116
|
+
icon: /* @__PURE__ */ jsx(SwapIcon, { className: "rotate-90" }),
|
|
117
|
+
label: t.swap,
|
|
118
|
+
onClick: () => setSeed({
|
|
119
|
+
base: seed.accent,
|
|
120
|
+
accent: seed.base
|
|
121
|
+
})
|
|
122
|
+
}),
|
|
113
123
|
value: seed.accent,
|
|
114
124
|
onValueChange: (accent) => setSeed({ accent })
|
|
115
125
|
}),
|
package/dist/theme/derive.js
CHANGED
|
@@ -402,6 +402,10 @@ function build(scheme, options) {
|
|
|
402
402
|
}
|
|
403
403
|
const sidebarBase = scheme.sidebar?.base ? oklch(scheme.sidebar.base) : neutral(dark ? Math.max(.08, base.l - .035 * s) : base.l - .035 * s);
|
|
404
404
|
const sidebarAccent = scheme.sidebar?.accent ? oklch(scheme.sidebar.accent) : accent;
|
|
405
|
+
const activeTint = sidebarAccent.c < .02 ? sidebarBase : {
|
|
406
|
+
...sidebarAccent,
|
|
407
|
+
c: Math.min(sidebarAccent.c, .08)
|
|
408
|
+
};
|
|
405
409
|
const sidebarDark = isDarkColor(toHex(sidebarBase));
|
|
406
410
|
const sidebarDir = sidebarDark ? 1 : -1;
|
|
407
411
|
set("--theme-sidebar-bg", sidebarBase);
|
|
@@ -409,17 +413,18 @@ function build(scheme, options) {
|
|
|
409
413
|
...sidebarBase,
|
|
410
414
|
l: sidebarBase.l + sidebarDir * (sidebarDark ? .08 : .05) * s
|
|
411
415
|
});
|
|
412
|
-
const activeAt = (f) => ({
|
|
413
|
-
l: sidebarBase.l +
|
|
414
|
-
c:
|
|
415
|
-
h:
|
|
416
|
+
const activeAt = (dir) => (f) => ({
|
|
417
|
+
l: sidebarBase.l + dir * (sidebarDark ? .12 : .07) * s * f,
|
|
418
|
+
c: activeTint.c,
|
|
419
|
+
h: activeTint.h
|
|
416
420
|
});
|
|
417
|
-
|
|
421
|
+
const [active, room] = [activeAt(sidebarDir), activeAt(-sidebarDir)].map((fill) => [fill, roomFor(fill, t.primary)]).reduce((a, b) => b[1] > a[1] ? b : a);
|
|
422
|
+
set("--theme-sidebar-active-bg", active(room));
|
|
418
423
|
solved("--theme-sidebar-text", inkFor(sidebarBase, sidebarBase, sidebarDark), ["--theme-sidebar-bg", "--theme-sidebar-hover"], t.primary);
|
|
419
424
|
solved("--theme-sidebar-active-text", {
|
|
420
425
|
l: sidebarBase.l,
|
|
421
|
-
c: Math.min(
|
|
422
|
-
h:
|
|
426
|
+
c: Math.min(activeTint.c, .04),
|
|
427
|
+
h: activeTint.h
|
|
423
428
|
}, ["--theme-sidebar-active-bg"], t.primary);
|
|
424
429
|
const style = options.code ?? "balanced";
|
|
425
430
|
set("--theme-code-bg", mutedPanel);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parallelworks/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.60.0",
|
|
4
4
|
"description": "React UI components: a theme contract, icons, brand logos, primitives, lists, forms, a job graph, a code editor, a log viewer, a file explorer and an AI chat, each on its own subpath",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|