@gtkx/storybook 0.0.1 → 2.0.0-beta.11

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/src/controls.tsx CHANGED
@@ -7,6 +7,9 @@ import type { Args, ArgTypes } from "./types.js";
7
7
 
8
8
  type ControlsProps = { argTypes: ArgTypes; args: Args; onChange: (update: Args) => void };
9
9
 
10
+ const NO_SELECTION_ID = "no-selection";
11
+ const NO_SELECTION_LABEL = "Choose option...";
12
+
10
13
  type ControlProps = {
11
14
  argument: string;
12
15
  title: string;
@@ -79,10 +82,7 @@ const NumberControl = ({
79
82
  />
80
83
  )}
81
84
  onNotifyValue={(next) => {
82
- if (
83
- typeof next === "number" && Number.isFinite(next) &&
84
- next >= min && next <= max && !Object.is(next, value)
85
- ) {
85
+ if (!Object.is(next, value)) {
86
86
  onChange({ [argument]: next });
87
87
  }
88
88
  }}
@@ -100,11 +100,11 @@ const SelectControl = (props: Omit<ControlProps, "type">): ReactNode => {
100
100
  const values: unknown[] = options;
101
101
  const selected = values.findIndex((option) => Object.is(option, value));
102
102
  const labels = isObject(settings.labels) ? settings.labels : {};
103
- const items = values.map((option, index) => {
103
+ const items = [{ id: NO_SELECTION_ID, value: NO_SELECTION_LABEL }, ...values.map((option, index) => {
104
104
  const label = labels[String(option)];
105
105
 
106
106
  return { id: String(index), value: typeof label === "string" ? label : String(option) };
107
- });
107
+ })];
108
108
 
109
109
  return (
110
110
  <ComboRow
@@ -112,13 +112,19 @@ const SelectControl = (props: Omit<ControlProps, "type">): ReactNode => {
112
112
  title={markupEscapeText(title, -1)}
113
113
  sensitive={!isDisabled}
114
114
  items={items}
115
- selectedId={selected === -1 ? null : String(selected)}
115
+ selectedId={selected === -1 ? NO_SELECTION_ID : String(selected)}
116
116
  onSelectionChanged={(id) => {
117
- const index = Number(id);
117
+ if (id === NO_SELECTION_ID) {
118
+ onChange({ [argument]: undefined });
119
+
120
+ return;
121
+ }
118
122
 
119
- if (Number.isSafeInteger(index) && index >= 0 && index < values.length) {
120
- onChange({ [argument]: values[index] });
123
+ if (id === null) {
124
+ return;
121
125
  }
126
+
127
+ onChange({ [argument]: values[Number(id)] });
122
128
  }}
123
129
  />
124
130
  );
@@ -136,7 +142,7 @@ const Control = (props: ControlProps): ReactNode => {
136
142
  sensitive={!isDisabled}
137
143
  active={value === true}
138
144
  onNotifyActive={(active) => {
139
- if (typeof active === "boolean" && !Object.is(active, value)) {
145
+ if (!Object.is(active, value)) {
140
146
  onChange({ [argument]: active });
141
147
  }
142
148
  }}
@@ -151,7 +157,7 @@ const Control = (props: ControlProps): ReactNode => {
151
157
  sensitive={!isDisabled}
152
158
  text={typeof value === "string" ? value : ""}
153
159
  onNotifyText={(text) => {
154
- if (typeof text === "string" && !Object.is(text, value)) {
160
+ if (!Object.is(text, value)) {
155
161
  onChange({ [argument]: text });
156
162
  }
157
163
  }}
@@ -177,9 +183,9 @@ const Controls = ({ argTypes, args, onChange }: ControlsProps): ReactNode => (
177
183
  <AdwPreferencesGroup title="Controls">
178
184
  {Object.entries(argTypes).map(([argument, annotation]) => {
179
185
  const control: unknown = annotation?.control;
180
- const table: unknown = annotation?.table;
186
+ const table = isObject(annotation?.table) ? annotation.table : {};
181
187
 
182
- if (control === undefined || control === false || (isObject(table) && table.disable === true)) {
188
+ if (control === undefined || control === false || table.disable === true) {
183
189
  return null;
184
190
  }
185
191
 
@@ -195,7 +201,7 @@ const Controls = ({ argTypes, args, onChange }: ControlsProps): ReactNode => (
195
201
  type={typeof type === "string" ? type : "unknown"}
196
202
  settings={settings}
197
203
  options={annotation?.options}
198
- isDisabled={settings.disable === true}
204
+ isDisabled={settings.disable === true || table.readonly === true}
199
205
  onChange={onChange}
200
206
  />
201
207
  );
package/src/types.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import type * as Gtk from "@gtkx/gi/gtk";
2
2
  import type { ComponentType, ReactNode } from "react";
3
3
  import type {
4
+ ArgsFromMeta,
4
5
  ComponentAnnotations,
5
6
  GlobalTypes,
6
7
  Renderer,
8
+ StoryAnnotations as StorybookAnnotations,
7
9
  ArgTypes as StorybookArgTypes,
8
10
  StoryContext as StorybookContext,
9
11
  } from "storybook/internal/types";
@@ -87,31 +89,11 @@ type ComponentOrProps<T> = T extends ComponentType<infer Props extends object>
87
89
  /** Presents combined inferred args as a single object type. */
88
90
  type Simplify<T> = { [Key in keyof T]: T[Key] };
89
91
 
90
- /** Combines the argument requirements of every member of a union. */
91
- type UnionToIntersection<T> = (
92
- T extends unknown ? (value: T) => void : never
93
- ) extends (value: infer Intersection) => void ? Intersection : never;
94
-
95
- /** Retains explicitly named args while removing broad index signatures. */
96
- type DeclaredArgs<T> = {
97
- [Key in keyof T as string extends Key
98
- ? never
99
- : number extends Key ? never : symbol extends Key ? never : Key]: T[Key];
100
- };
101
-
102
- /** Extracts the args accepted by a custom render function. */
103
- type RenderArgs<T> = T extends (args: infer Props extends object, context: never) => ReactNode ? Props : object;
104
-
105
- /** Combines the args required by a metadata object's decorators. */
106
- type DecoratorArgs<T> = T extends readonly (infer Item)[]
107
- ? UnionToIntersection<Item extends Decorator<infer Props extends object> ? Props : object>
108
- : object;
109
-
110
92
  /** Infers story args from component props, render functions, decorators, or declared defaults. */
111
- type ArgsFrom<T> = T extends { component?: infer Component; render?: infer Render; decorators?: infer Decorators }
93
+ type ArgsFrom<T> = T extends { component?: infer Component; render?: unknown; decorators?: unknown }
112
94
  ? Simplify<
113
95
  (NonNullable<Component> extends ComponentType<infer Props extends object> ? Props : object) &
114
- DeclaredArgs<RenderArgs<NonNullable<Render>> & DecoratorArgs<NonNullable<Decorators>>>
96
+ ArgsFromMeta<NativeRenderer, T>
115
97
  >
116
98
  : T extends { args: infer Defaults extends object } ? Defaults : Args;
117
99
 
@@ -135,9 +117,10 @@ type RequiredStoryArgs<T, TArgs extends object> =
135
117
 
136
118
  /** CSF3 story object inferred from metadata, a React component, or an explicit args type. */
137
119
  type StoryObj<T = Args> = T extends { component?: unknown; render?: unknown; decorators?: unknown; args?: unknown }
138
- ? StoryAnnotations<ArgsFrom<T>> & (Record<never, never> extends RequiredStoryArgs<T, ArgsFrom<T>>
139
- ? { args?: RequiredStoryArgs<T, ArgsFrom<T>> }
140
- : { args: RequiredStoryArgs<T, ArgsFrom<T>> })
120
+ ? StoryAnnotations<ArgsFrom<T>> & Pick<
121
+ StorybookAnnotations<NativeRenderer<ArgsFrom<T>>, ArgsFrom<T>, RequiredStoryArgs<T, ArgsFrom<T>>>,
122
+ "args"
123
+ >
141
124
  : StoryAnnotations<ComponentOrProps<T>>;
142
125
 
143
126
  /** Project annotations shared by all composed stories. */