@openpen/module-api 1.2.0 → 1.4.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +7 -1
  3. package/dist/_chunks/{AppButtonDropdown.vue_vue_type_style_index_0_lang-DBVFUpxc.js → AppButtonDropdown.vue_vue_type_style_index_0_lang-B9dHU-LE.js} +3 -2
  4. package/dist/_chunks/AppButtonDropdown.vue_vue_type_style_index_0_lang-B9dHU-LE.js.map +1 -0
  5. package/dist/host/index.d.ts +1 -1
  6. package/dist/host/index.js +2 -0
  7. package/dist/host/index.js.map +1 -1
  8. package/dist/host/stroke-store.d.ts +1 -0
  9. package/dist/host/tools.d.ts +9 -0
  10. package/dist/host/types.d.ts +19 -0
  11. package/dist/index.d.ts +1 -0
  12. package/dist/index.js +5 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/types/contributions.d.ts +7 -5
  15. package/dist/types/control-bar-layout.d.ts +19 -148
  16. package/dist/types/module.d.ts +7 -1
  17. package/dist/types/tool.d.ts +14 -3
  18. package/dist/uikit/components/AppButtonDropdown.vue.d.ts +1 -1
  19. package/dist/uikit/components/AppPopoverPanel.vue.d.ts +28 -0
  20. package/dist/uikit/components/AppPopoverRow.vue.d.ts +26 -0
  21. package/dist/uikit/components/AppSegmented.vue.d.ts +6 -1
  22. package/dist/uikit/components/AppSelect.vue.d.ts +7 -0
  23. package/dist/uikit/components/AppSlider.vue.d.ts +14 -0
  24. package/dist/uikit/components/AppSwatchPicker.vue.d.ts +37 -0
  25. package/dist/uikit/components/AppToggle.vue.d.ts +2 -0
  26. package/dist/uikit/components/AppToggleButton.vue.d.ts +28 -0
  27. package/dist/uikit/index.d.ts +9 -3
  28. package/dist/uikit/index.js +346 -109
  29. package/dist/uikit/index.js.map +1 -1
  30. package/dist/uikit/internal.js +1 -1
  31. package/dist/uikit/module-api.css +287 -86
  32. package/dist/uikit/primitives.d.ts +4 -2
  33. package/dist/uikit/tokens.css +7 -6
  34. package/dist/use-module-context.d.ts +1 -2
  35. package/package.json +4 -4
  36. package/dist/_chunks/AppButtonDropdown.vue_vue_type_style_index_0_lang-DBVFUpxc.js.map +0 -1
@@ -3,166 +3,37 @@ import type { Component } from 'vue';
3
3
  import type { LocaleMap } from '../locale';
4
4
  export declare const GroupInsetSchema: z.ZodObject<{
5
5
  enabled: z.ZodBoolean;
6
- /** Optional CSS color override for the inset background; defaults to --openpen-color-control-group. */
7
6
  color: z.ZodOptional<z.ZodString>;
8
- }, "strip", z.ZodTypeAny, {
9
- enabled: boolean;
10
- color?: string | undefined;
11
- }, {
12
- enabled: boolean;
13
- color?: string | undefined;
14
- }>;
7
+ }, z.core.$strip>;
15
8
  export declare const LayoutGroupSchema: z.ZodObject<{
16
9
  id: z.ZodString;
17
- items: z.ZodArray<z.ZodString, "many">;
18
- separator: z.ZodOptional<z.ZodEnum<["auto", "always", "never"]>>;
19
- /**
20
- * Optional inset rendering for this group. When `enabled: true`, the group
21
- * MUST render with a visible bg + border + padding container (the design's
22
- * "grouped tools" look) AND its inner items MUST shrink so the group's
23
- * outer height matches an unwrapped 36px button — i.e. enabling inset
24
- * MUST NOT increase control-bar height.
25
- */
10
+ items: z.ZodArray<z.ZodString>;
11
+ separator: z.ZodOptional<z.ZodEnum<{
12
+ never: "never";
13
+ auto: "auto";
14
+ always: "always";
15
+ }>>;
26
16
  inset: z.ZodOptional<z.ZodObject<{
27
17
  enabled: z.ZodBoolean;
28
- /** Optional CSS color override for the inset background; defaults to --openpen-color-control-group. */
29
18
  color: z.ZodOptional<z.ZodString>;
30
- }, "strip", z.ZodTypeAny, {
31
- enabled: boolean;
32
- color?: string | undefined;
33
- }, {
34
- enabled: boolean;
35
- color?: string | undefined;
36
- }>>;
37
- }, "strip", z.ZodTypeAny, {
38
- id: string;
39
- items: string[];
40
- separator?: "never" | "auto" | "always" | undefined;
41
- inset?: {
42
- enabled: boolean;
43
- color?: string | undefined;
44
- } | undefined;
45
- }, {
46
- id: string;
47
- items: string[];
48
- separator?: "never" | "auto" | "always" | undefined;
49
- inset?: {
50
- enabled: boolean;
51
- color?: string | undefined;
52
- } | undefined;
53
- }>;
19
+ }, z.core.$strip>>;
20
+ }, z.core.$strip>;
54
21
  export declare const ControlBarLayoutSchema: z.ZodObject<{
55
22
  version: z.ZodLiteral<1>;
56
- groups: z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodArray<z.ZodObject<{
23
+ groups: z.ZodArray<z.ZodObject<{
57
24
  id: z.ZodString;
58
- items: z.ZodArray<z.ZodString, "many">;
59
- separator: z.ZodOptional<z.ZodEnum<["auto", "always", "never"]>>;
60
- /**
61
- * Optional inset rendering for this group. When `enabled: true`, the group
62
- * MUST render with a visible bg + border + padding container (the design's
63
- * "grouped tools" look) AND its inner items MUST shrink so the group's
64
- * outer height matches an unwrapped 36px button — i.e. enabling inset
65
- * MUST NOT increase control-bar height.
66
- */
25
+ items: z.ZodArray<z.ZodString>;
26
+ separator: z.ZodOptional<z.ZodEnum<{
27
+ never: "never";
28
+ auto: "auto";
29
+ always: "always";
30
+ }>>;
67
31
  inset: z.ZodOptional<z.ZodObject<{
68
32
  enabled: z.ZodBoolean;
69
- /** Optional CSS color override for the inset background; defaults to --openpen-color-control-group. */
70
33
  color: z.ZodOptional<z.ZodString>;
71
- }, "strip", z.ZodTypeAny, {
72
- enabled: boolean;
73
- color?: string | undefined;
74
- }, {
75
- enabled: boolean;
76
- color?: string | undefined;
77
- }>>;
78
- }, "strip", z.ZodTypeAny, {
79
- id: string;
80
- items: string[];
81
- separator?: "never" | "auto" | "always" | undefined;
82
- inset?: {
83
- enabled: boolean;
84
- color?: string | undefined;
85
- } | undefined;
86
- }, {
87
- id: string;
88
- items: string[];
89
- separator?: "never" | "auto" | "always" | undefined;
90
- inset?: {
91
- enabled: boolean;
92
- color?: string | undefined;
93
- } | undefined;
94
- }>, "many">, {
95
- id: string;
96
- items: string[];
97
- separator?: "never" | "auto" | "always" | undefined;
98
- inset?: {
99
- enabled: boolean;
100
- color?: string | undefined;
101
- } | undefined;
102
- }[], {
103
- id: string;
104
- items: string[];
105
- separator?: "never" | "auto" | "always" | undefined;
106
- inset?: {
107
- enabled: boolean;
108
- color?: string | undefined;
109
- } | undefined;
110
- }[]>, {
111
- id: string;
112
- items: string[];
113
- separator?: "never" | "auto" | "always" | undefined;
114
- inset?: {
115
- enabled: boolean;
116
- color?: string | undefined;
117
- } | undefined;
118
- }[], {
119
- id: string;
120
- items: string[];
121
- separator?: "never" | "auto" | "always" | undefined;
122
- inset?: {
123
- enabled: boolean;
124
- color?: string | undefined;
125
- } | undefined;
126
- }[]>, {
127
- id: string;
128
- items: string[];
129
- separator?: "never" | "auto" | "always" | undefined;
130
- inset?: {
131
- enabled: boolean;
132
- color?: string | undefined;
133
- } | undefined;
134
- }[], {
135
- id: string;
136
- items: string[];
137
- separator?: "never" | "auto" | "always" | undefined;
138
- inset?: {
139
- enabled: boolean;
140
- color?: string | undefined;
141
- } | undefined;
142
- }[]>;
143
- }, "strip", z.ZodTypeAny, {
144
- version: 1;
145
- groups: {
146
- id: string;
147
- items: string[];
148
- separator?: "never" | "auto" | "always" | undefined;
149
- inset?: {
150
- enabled: boolean;
151
- color?: string | undefined;
152
- } | undefined;
153
- }[];
154
- }, {
155
- version: 1;
156
- groups: {
157
- id: string;
158
- items: string[];
159
- separator?: "never" | "auto" | "always" | undefined;
160
- inset?: {
161
- enabled: boolean;
162
- color?: string | undefined;
163
- } | undefined;
164
- }[];
165
- }>;
34
+ }, z.core.$strip>>;
35
+ }, z.core.$strip>>;
36
+ }, z.core.$strip>;
166
37
  export interface GroupInset {
167
38
  enabled: boolean;
168
39
  /** Optional CSS color override for the inset background; defaults to --openpen-color-control-group. */
@@ -64,6 +64,11 @@ export interface OpenPenModule {
64
64
  * made via `ctx.updateSettings()`; writes that fail validation reject
65
65
  * with the underlying `ZodError`.
66
66
  *
67
+ * Nested object fields that need their inner defaults filled from an
68
+ * empty or invalid stored value MUST use `.prefault({})`, not
69
+ * `.default({})`: the host rebuilds invalid settings from `{}`, and
70
+ * `.default()` returns its value without parsing it.
71
+ *
67
72
  * Modules that intend to call `ctx.updateSettings()` MUST declare
68
73
  * this field; calling `updateSettings` without a schema throws at
69
74
  * runtime so the missing contract surfaces during development.
@@ -130,7 +135,8 @@ export interface ModuleSetupContext {
130
135
  * result against `settingsSchema` (Zod), and persists to `config.json`.
131
136
  * Resolves once the write is durable; rejects with the underlying
132
137
  * `ZodError` if the merged object fails validation (no I/O happens
133
- * on validation failure).
138
+ * on validation failure). Read the failures from `error.issues`;
139
+ * `ZodError` has no `.errors` property.
134
140
  *
135
141
  * The in-memory snapshot returned by `getSettings()` is updated
136
142
  * before the Promise resolves; subscribers registered via
@@ -37,6 +37,18 @@ export interface Stroke {
37
37
  tool: string;
38
38
  points: Point[];
39
39
  style: StrokeStyle;
40
+ /**
41
+ * Whole-stroke opacity in `0..1`; omitted means fully opaque.
42
+ *
43
+ * The host's default polyline renderer applies it as `globalAlpha` and clamps
44
+ * values outside `0..1` back into range (non-finite values are ignored). A
45
+ * tool that ships its own `renderStroke` owns the drawing and reads this field
46
+ * itself — the host does not wrap custom renderers, so a plugin that already
47
+ * stores and applies its own `opacity` key keeps rendering exactly as before.
48
+ * A tool WITHOUT `renderStroke` that stores an `opacity` key now has it applied
49
+ * by the default renderer; such a tool must store a number in `0..1`.
50
+ */
51
+ opacity?: number;
40
52
  /**
41
53
  * Tool-specific extra state. Tools MAY store arbitrary keys here during
42
54
  * `onPointerDown` / `onPointerMove` / `onPointerUp`; those keys survive
@@ -48,11 +60,10 @@ export interface Stroke {
48
60
  *
49
61
  * @example
50
62
  * // Store during onPointerUp:
51
- * const stroke: Stroke = { id, tool: 'my-tool', points, style, opacity: 0.5 }
63
+ * const stroke: Stroke = { id, tool: 'my-tool', points, style, taper: 0.5 }
52
64
  *
53
65
  * // Read back in renderStroke:
54
- * const opacity = (stroke.opacity as number) ?? 1
55
- * canvasCtx.globalAlpha = opacity
66
+ * const taper = (stroke.taper as number) ?? 1
56
67
  */
57
68
  [key: string]: unknown;
58
69
  }
@@ -35,7 +35,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {},
35
35
  disabled: boolean;
36
36
  active: boolean;
37
37
  variant: "default" | "danger";
38
- popoverPlacement: "auto" | "top" | "bottom" | "left" | "right";
38
+ popoverPlacement: "auto" | "left" | "right" | "top" | "bottom";
39
39
  mainTooltip: string;
40
40
  mainAriaLabel: string;
41
41
  caretAriaLabel: string;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * AppPopoverPanel - High-level wrapper (Layer 1).
3
+ *
4
+ * Inner layout for the `content` slot of AppPopover: a vertical stack with the
5
+ * same 10px spacing the host's own popup panels use, plus an optional title.
6
+ * Rows share three columns (label, control, value) so controls start at the
7
+ * same x in every row without any plugin-side CSS.
8
+ * The frame (background, border, radius, padding, shadow) comes from AppPopover.
9
+ *
10
+ * Styles use --openpen-* design tokens only.
11
+ */
12
+ type __VLS_Props = {
13
+ /** Optional small-caps heading rendered above the panel content. */
14
+ title?: string;
15
+ };
16
+ declare var __VLS_1: {};
17
+ type __VLS_Slots = {} & {
18
+ default?: (props: typeof __VLS_1) => any;
19
+ };
20
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
22
+ declare const _default: typeof __VLS_export;
23
+ export default _default;
24
+ type __VLS_WithSlots<T, S> = T & {
25
+ new (): {
26
+ $slots: S;
27
+ };
28
+ };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * AppPopoverRow - High-level wrapper (Layer 1).
3
+ *
4
+ * One form row inside an AppPopoverPanel: an optional label followed by a
5
+ * control (toggle, slider, segmented control, ...) in the default slot, and an
6
+ * optional third element (value text such as "150px") that is right-aligned in
7
+ * the panel's shared value column.
8
+ * Spacing matches the host's own popup rows (10px gap, vertically centred).
9
+ */
10
+ type __VLS_Props = {
11
+ /** Optional label rendered before the control. */
12
+ label?: string;
13
+ };
14
+ declare var __VLS_1: {};
15
+ type __VLS_Slots = {} & {
16
+ default?: (props: typeof __VLS_1) => any;
17
+ };
18
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
19
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
20
+ declare const _default: typeof __VLS_export;
21
+ export default _default;
22
+ type __VLS_WithSlots<T, S> = T & {
23
+ new (): {
24
+ $slots: S;
25
+ };
26
+ };
@@ -2,13 +2,18 @@ interface Option {
2
2
  value: string;
3
3
  label: string;
4
4
  icon?: string;
5
+ /** Show only the icon; `label` becomes the accessible name and the tooltip. */
6
+ iconOnly?: boolean;
7
+ /** Tooltip text; defaults to `label` for icon-only options. */
8
+ tooltip?: string;
5
9
  testid?: string;
6
10
  }
7
11
  type __VLS_Props = {
8
12
  modelValue: string;
9
13
  options: Option[];
10
- /** When true, all options are non-interactive and visually dimmed. */
11
14
  disabled?: boolean;
15
+ /** Accessible name of the whole group (e.g. "Head style"). */
16
+ ariaLabel?: string;
12
17
  };
13
18
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
14
19
  "update:modelValue": (value: string) => any;
@@ -14,6 +14,12 @@ export interface AppSelectProps {
14
14
  placeholder: string;
15
15
  /** Whether the select is disabled. */
16
16
  disabled?: boolean;
17
+ /**
18
+ * Accessible name of the trigger button. Pass it whenever the select has no
19
+ * visible label of its own; otherwise a screen reader announces only the
20
+ * current value.
21
+ */
22
+ ariaLabel?: string;
17
23
  }
18
24
  declare const __VLS_export: import("vue").DefineComponent<AppSelectProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
19
25
  "update:modelValue": (value: string) => any;
@@ -21,6 +27,7 @@ declare const __VLS_export: import("vue").DefineComponent<AppSelectProps, {}, {}
21
27
  "onUpdate:modelValue"?: ((value: string) => any) | undefined;
22
28
  }>, {
23
29
  disabled: boolean;
30
+ ariaLabel: string;
24
31
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
25
32
  declare const _default: typeof __VLS_export;
26
33
  export default _default;
@@ -5,6 +5,11 @@ type __VLS_Props = {
5
5
  step?: number;
6
6
  /** Container width (e.g. '100%', '72px'). In vertical mode this sets the height. */
7
7
  width?: string;
8
+ /**
9
+ * Accessible name announced by screen readers when the thumb is focused.
10
+ * Pass it whenever the slider has no visible label of its own.
11
+ */
12
+ ariaLabel?: string;
8
13
  orientation?: 'horizontal' | 'vertical';
9
14
  trackHeight?: string;
10
15
  trackRadius?: string;
@@ -21,6 +26,13 @@ type __VLS_Props = {
21
26
  * startEdge/endEdge on SliderRange — no manual value transformation needed.
22
27
  */
23
28
  inverted?: boolean;
29
+ /**
30
+ * Text for the value bubble (e.g. "4px"). When set, a small bubble with this
31
+ * text appears above the thumb while the slider is being dragged and hides on
32
+ * release; it is also exposed to assistive technology as `aria-valuetext`.
33
+ * Horizontal sliders only. Leave unset for no bubble.
34
+ */
35
+ valueLabel?: string;
24
36
  };
25
37
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
26
38
  "update:modelValue": (value: number) => any;
@@ -31,6 +43,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
31
43
  min: number;
32
44
  max: number;
33
45
  step: number;
46
+ ariaLabel: string;
34
47
  orientation: "horizontal" | "vertical";
35
48
  trackHeight: string;
36
49
  trackRadius: string;
@@ -38,6 +51,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
38
51
  thumbHeight: string;
39
52
  thumbRadius: string;
40
53
  inverted: boolean;
54
+ valueLabel: string;
41
55
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
42
56
  declare const _default: typeof __VLS_export;
43
57
  export default _default;
@@ -0,0 +1,37 @@
1
+ export interface SwatchColor {
2
+ /** CSS colour value, e.g. `#818CF8`. Compared case-insensitively with `modelValue`. */
3
+ value: string;
4
+ /** Accessible name announced for the swatch (for example `Indigo`). */
5
+ label: string;
6
+ /** Optional `data-testid` for the swatch button. */
7
+ testid?: string;
8
+ }
9
+ type __VLS_Props = {
10
+ /** Currently selected colour value (use `v-model`). */
11
+ modelValue: string;
12
+ colors: SwatchColor[];
13
+ /** Accessible name of the whole group. */
14
+ ariaLabel: string;
15
+ shape?: 'circular' | 'rounded' | 'square';
16
+ size?: 'small' | 'medium' | 'large';
17
+ /** Gap between swatches: `small` 6px, `medium` 8px. */
18
+ spacing?: 'small' | 'medium';
19
+ /** Swatch background override, for example a gradient. Defaults to the colour value. */
20
+ background?: (color: SwatchColor) => string;
21
+ disabled?: boolean;
22
+ testid?: string;
23
+ };
24
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
25
+ "update:modelValue": (value: string) => any;
26
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
27
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
28
+ }>, {
29
+ disabled: boolean;
30
+ testid: string;
31
+ shape: "square" | "rounded" | "circular";
32
+ size: "small" | "medium" | "large";
33
+ spacing: "small" | "medium";
34
+ background: (color: SwatchColor) => string;
35
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
36
+ declare const _default: typeof __VLS_export;
37
+ export default _default;
@@ -1,6 +1,7 @@
1
1
  type __VLS_Props = {
2
2
  modelValue: boolean;
3
3
  ariaLabel?: string;
4
+ testid?: string;
4
5
  };
5
6
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
7
  "update:modelValue": (value: boolean) => any;
@@ -8,6 +9,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
8
9
  "onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
9
10
  }>, {
10
11
  ariaLabel: string;
12
+ testid: string;
11
13
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
12
14
  declare const _default: typeof __VLS_export;
13
15
  export default _default;
@@ -0,0 +1,28 @@
1
+ type __VLS_Props = {
2
+ /** Pressed state (use `v-model`). */
3
+ modelValue: boolean;
4
+ /** Accessible name. Required because the content is often a single glyph or icon. */
5
+ ariaLabel: string;
6
+ disabled?: boolean;
7
+ testid?: string;
8
+ };
9
+ declare var __VLS_9: {};
10
+ type __VLS_Slots = {} & {
11
+ default?: (props: typeof __VLS_9) => any;
12
+ };
13
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
14
+ "update:modelValue": (value: boolean) => any;
15
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
16
+ "onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
17
+ }>, {
18
+ disabled: boolean;
19
+ testid: string;
20
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
22
+ declare const _default: typeof __VLS_export;
23
+ export default _default;
24
+ type __VLS_WithSlots<T, S> = T & {
25
+ new (): {
26
+ $slots: S;
27
+ };
28
+ };
@@ -12,17 +12,23 @@
12
12
  * Note: you must manually handle modal-manager, animating guard,
13
13
  * passthrough, and teleport target when walking this layer.
14
14
  *
15
- * Layer 3 — Escape Hatch (5% fully custom)
16
- * Plugin installs reka-ui (or any library) directly in its own package.json.
17
- * UIKit MUST NOT block this. Not handled here — plugin author's choice.
15
+ * Layer 3 — Custom Components (5% fully custom)
16
+ * Plugin builds its own components on top of the Layer 2 primitives and the
17
+ * --openpen-* design tokens. Plugins MUST NOT install or import reka-ui
18
+ * directly; headless primitives come only from this entry point.
18
19
  *
19
20
  * See docs/uikit/index.md for the full trade-off description.
20
21
  */
21
22
  export { default as AppPopover } from './components/AppPopover.vue';
22
23
  export type { AppPopoverProps, Placement } from './components/AppPopover.vue';
24
+ export { default as AppPopoverPanel } from './components/AppPopoverPanel.vue';
25
+ export { default as AppPopoverRow } from './components/AppPopoverRow.vue';
23
26
  export { default as AppSlider } from './components/AppSlider.vue';
24
27
  export { default as AppToggle } from './components/AppToggle.vue';
25
28
  export { default as AppSegmented } from './components/AppSegmented.vue';
29
+ export { default as AppSwatchPicker } from './components/AppSwatchPicker.vue';
30
+ export type { SwatchColor } from './components/AppSwatchPicker.vue';
31
+ export { default as AppToggleButton } from './components/AppToggleButton.vue';
26
32
  export { default as AppDialog } from './components/AppDialog.vue';
27
33
  export type { AppDialogProps } from './components/AppDialog.vue';
28
34
  export { useDialog } from './composables/useDialog';