@vicinae/api 0.8.2 → 0.8.4

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/README.md CHANGED
@@ -5,6 +5,12 @@ This package lets you extend the [Vicinae](https://docs.vicinae.com/) launcher u
5
5
 
6
6
  # Getting started
7
7
 
8
+ The recommend way to start developing a new extension is to [read the docs](https://docs.vicinae.com/extensions/introduction).
9
+
10
+ You can stop reading this.
11
+
12
+ # Installation
13
+
8
14
  Install the package:
9
15
 
10
16
  ```
package/dist/api/ai.js CHANGED
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AI = void 0;
4
4
  const stream_1 = require("stream");
5
- const bus_1 = require("./bus");
6
5
  const crypto_1 = require("crypto");
6
+ const bus_1 = require("./bus");
7
7
  var AI;
8
8
  (function (AI) {
9
9
  /**
package/dist/api/bus.d.ts CHANGED
@@ -82,6 +82,12 @@ declare class Bus {
82
82
  };
83
83
  emit(action: string, data: Record<string, any>): void;
84
84
  sendMessage(message: ipc.ExtensionMessage): void;
85
+ addEventHandler(cb: EventListenerInfo['callback']): {
86
+ id: string;
87
+ unsubscribe: () => void;
88
+ };
89
+ replaceEventHandler(id: string, handler: EventListenerInfo['callback']): void;
90
+ removeEventHandler(id: string): void;
85
91
  request2(data: extension.RequestData, options?: {
86
92
  timeout?: number;
87
93
  }): Promise<Result<extension.ResponseData, Error>>;
@@ -90,6 +96,9 @@ declare class Bus {
90
96
  rejectOnError?: boolean;
91
97
  }): Promise<Message<T>>;
92
98
  }
93
- export declare const createHandler: (handler: (...args: any[]) => void) => string;
99
+ /**
100
+ * IPC bus to communicate with the extension manager.
101
+ * If you are using this from inside your extension, you are WRONG and you should stop.
102
+ */
94
103
  export declare const bus: Bus;
95
104
  export {};
package/dist/api/bus.js CHANGED
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.bus = exports.createHandler = void 0;
36
+ exports.bus = void 0;
37
37
  const crypto_1 = require("crypto");
38
38
  const worker_threads_1 = require("worker_threads");
39
39
  const ipc = __importStar(require("./proto/ipc"));
@@ -142,6 +142,19 @@ class Bus {
142
142
  sendMessage(message) {
143
143
  this.port.postMessage(ipc.ExtensionMessage.encode(message).finish());
144
144
  }
145
+ addEventHandler(cb) {
146
+ const id = `handler-${(0, crypto_1.randomUUID)()}`;
147
+ const { unsubscribe } = this.subscribe(id, cb);
148
+ return { id, unsubscribe };
149
+ }
150
+ replaceEventHandler(id, handler) {
151
+ for (const listener of this.eventListeners.get(id) ?? []) {
152
+ listener.callback = handler;
153
+ }
154
+ }
155
+ removeEventHandler(id) {
156
+ this.eventListeners.delete(id);
157
+ }
145
158
  request2(data, options = {}) {
146
159
  const req = extension.Request.create({ requestId: (0, crypto_1.randomUUID)(), data });
147
160
  return new Promise((resolve, reject) => {
@@ -202,10 +215,8 @@ class Bus {
202
215
  });
203
216
  }
204
217
  }
205
- const createHandler = (handler) => {
206
- const id = (0, crypto_1.randomUUID)();
207
- exports.bus.subscribe(id, handler);
208
- return id;
209
- };
210
- exports.createHandler = createHandler;
218
+ /**
219
+ * IPC bus to communicate with the extension manager.
220
+ * If you are using this from inside your extension, you are WRONG and you should stop.
221
+ */
211
222
  exports.bus = new Bus(worker_threads_1.parentPort);
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ActionPanel = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const image_1 = require("../image");
6
- const hooks_1 = require("../hooks");
7
6
  const ActionPanelRoot = (props) => {
8
7
  const nativeProps = props;
9
8
  return (0, jsx_runtime_1.jsx)("action-panel", { ...nativeProps });
@@ -15,11 +14,7 @@ const ActionPanelSection = (props) => {
15
14
  return ((0, jsx_runtime_1.jsx)("action-panel-section", { ...nativeProps, children: props.children }));
16
15
  };
17
16
  const ActionPannelSubmenu = ({ icon, children, onOpen, onSearchTextChange, ...props }) => {
18
- const onSearchTextChangeHandler = (0, hooks_1.useEventListener)(onSearchTextChange);
19
- const onOpenHandler = (0, hooks_1.useEventListener)(onOpen);
20
17
  const nativeProps = props;
21
- nativeProps.onSearchTextChange = onSearchTextChangeHandler;
22
- nativeProps.onOpen = onOpenHandler;
23
18
  if (icon)
24
19
  nativeProps.icon = (0, image_1.serializeImageLike)(icon);
25
20
  return ((0, jsx_runtime_1.jsx)("action-panel-submenu", { ...nativeProps, children: children }));
@@ -6,15 +6,11 @@ const index_1 = require("../hooks/index");
6
6
  const clipboard_1 = require("../clipboard");
7
7
  const image_1 = require("../image");
8
8
  const utils_1 = require("../utils");
9
- const hooks_1 = require("../hooks");
10
9
  const icon_1 = require("../icon");
11
10
  const controls_1 = require("../controls");
12
11
  const ActionRoot = ({ icon, ...props }) => {
13
- const handler = (0, hooks_1.useEventListener)(props.onAction);
14
12
  const nativeProps = {
15
13
  ...props,
16
- icon,
17
- onAction: handler,
18
14
  };
19
15
  if (icon) {
20
16
  nativeProps.icon = (0, image_1.serializeImageLike)(icon);
@@ -52,15 +48,11 @@ const Push = ({ target, ...props }) => {
52
48
  push(target);
53
49
  } }));
54
50
  };
55
- const SubmitForm = ({ onSubmit, icon, title = "Submit", ...props }) => {
56
- const submitHandler = (0, hooks_1.useEventListener)(onSubmit);
57
- const handler = (0, hooks_1.useEventListener)(() => { });
51
+ const SubmitForm = ({ icon, title = "Submit", ...props }) => {
58
52
  const nativeProps = {
59
53
  ...props,
60
54
  title,
61
- icon,
62
- onSubmit: submitHandler,
63
- onAction: handler,
55
+ onAction: () => { }
64
56
  };
65
57
  if (icon) {
66
58
  nativeProps.icon = (0, image_1.serializeImageLike)(icon);
@@ -3,14 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Dropdown = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const image_1 = require("../image");
6
- const hooks_1 = require("../hooks");
7
6
  const DropdownRoot = ({ children, ...props }) => {
8
- const onSearchTextChange = (0, hooks_1.useEventListener)(props.onSearchTextChange);
9
- const onChange = (0, hooks_1.useEventListener)(props.onChange);
10
- return ((0, jsx_runtime_1.jsx)("dropdown", { onSearchTextChange: onSearchTextChange, onChange: onChange, children: children }));
7
+ return ((0, jsx_runtime_1.jsx)("dropdown", { ...props, children: children }));
11
8
  };
12
9
  const Item = ({ title, value, icon }) => {
13
- return ((0, jsx_runtime_1.jsx)("dropdown-item", { title: title, value: value, icon: icon && (0, image_1.serializeImageLike)(icon) }));
10
+ return ((0, jsx_runtime_1.jsx)("dropdown-item", { title: title, value: value, icon: icon ? (0, image_1.serializeImageLike)(icon) : undefined }));
14
11
  };
15
12
  const Section = ({ title, children }) => {
16
13
  return (0, jsx_runtime_1.jsx)("dropdown-section", { title: title, children: children });
@@ -3,16 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Form = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const use_imperative_form_handle_1 = require("../hooks/use-imperative-form-handle");
6
- const hooks_1 = require("../hooks");
7
6
  const FormRoot = ({ enableDrafts = false, actions, children, isLoading = false, navigationTitle, searchBarAccessory, }) => {
8
7
  return ((0, jsx_runtime_1.jsxs)("form", { enableDrafts: enableDrafts, isLoading: isLoading, navigationTitle: navigationTitle, children: [searchBarAccessory, children, actions] }));
9
8
  };
10
- const TextField = ({ ref, onChange, onBlur, onFocus, ...props }) => {
9
+ const TextField = ({ ref, ...props }) => {
11
10
  (0, use_imperative_form_handle_1.useImperativeFormHandle)(ref);
12
- const blur = (0, hooks_1.useEventListener)(onBlur);
13
- const focus = (0, hooks_1.useEventListener)(onFocus);
14
- const change = (0, hooks_1.useEventListener)(onChange);
15
- return ((0, jsx_runtime_1.jsx)("text-field", { onBlur: blur, onFocus: focus, onChange: change, ...props }));
11
+ return ((0, jsx_runtime_1.jsx)("text-field", { ...props }));
16
12
  };
17
13
  const PasswordField = ({ ...props }) => {
18
14
  return (0, jsx_runtime_1.jsx)("password-field", { ...props });
@@ -20,20 +16,12 @@ const PasswordField = ({ ...props }) => {
20
16
  const DatePicker = ({ ...props }) => {
21
17
  return (0, jsx_runtime_1.jsx)("date-picker-field", { ...props });
22
18
  };
23
- const Checkbox = ({ ref, onBlur, onFocus, onChange, ...props }) => {
19
+ const Checkbox = ({ ref, ...props }) => {
24
20
  (0, use_imperative_form_handle_1.useImperativeFormHandle)(ref);
25
- const blur = (0, hooks_1.useEventListener)(onBlur);
26
- const focus = (0, hooks_1.useEventListener)(onFocus);
27
- const change = (0, hooks_1.useEventListener)(onChange);
28
- return ((0, jsx_runtime_1.jsx)("checkbox-field", { onBlur: blur, onFocus: focus, onChange: change, ...props }));
21
+ return ((0, jsx_runtime_1.jsx)("checkbox-field", { ...props }));
29
22
  };
30
- const Dropdown = ({ children, onBlur, onFocus, onChange, ...props }) => {
31
- const onSearchTextChange = (0, hooks_1.useEventListener)(props.onSearchTextChange);
32
- const blur = (0, hooks_1.useEventListener)(onBlur);
33
- const focus = (0, hooks_1.useEventListener)(onFocus);
34
- const change = (0, hooks_1.useEventListener)(onChange);
35
- const rest = { ...props, onSearchTextChange };
36
- return ((0, jsx_runtime_1.jsx)("dropdown-field", { onBlur: blur, onFocus: focus, onChange: change, ...rest, children: children }));
23
+ const Dropdown = ({ children, ...props }) => {
24
+ return ((0, jsx_runtime_1.jsx)("dropdown-field", { ...props, children: children }));
37
25
  };
38
26
  exports.Form = Object.assign(FormRoot, {
39
27
  TextField,
@@ -6,7 +6,6 @@ const react_1 = require("react");
6
6
  const image_1 = require("../image");
7
7
  const crypto_1 = require("crypto");
8
8
  const empty_view_1 = require("./empty-view");
9
- const hooks_1 = require("../hooks");
10
9
  const dropdown_1 = require("./dropdown");
11
10
  var GridInset;
12
11
  (function (GridInset) {
@@ -19,14 +18,12 @@ var GridFit;
19
18
  GridFit["Contain"] = "contain";
20
19
  GridFit["Fill"] = "fill";
21
20
  })(GridFit || (GridFit = {}));
22
- const GridRoot = ({ onSearchTextChange, searchBarAccessory, onSelectionChange, children, actions, inset, fit = GridFit.Contain, aspectRatio = "1", ...props }) => {
23
- const searchTextChangeHandler = (0, hooks_1.useEventListener)(onSearchTextChange);
24
- const selectionChangeHandler = (0, hooks_1.useEventListener)(onSelectionChange);
21
+ const GridRoot = ({ searchBarAccessory, children, actions, inset, fit = GridFit.Contain, aspectRatio = "1", ...props }) => {
25
22
  if (typeof props.enableFiltering === "boolean" &&
26
23
  typeof props.filtering === "undefined") {
27
24
  props.filtering = props.enableFiltering;
28
25
  }
29
- return ((0, jsx_runtime_1.jsxs)("grid", { fit: fit, inset: inset, aspectRatio: aspectRatio, onSearchTextChange: searchTextChangeHandler, onSelectionChange: selectionChangeHandler, ...props, children: [searchBarAccessory, children, actions] }));
26
+ return ((0, jsx_runtime_1.jsxs)("grid", { fit: fit, inset: inset, aspectRatio: aspectRatio, ...props, children: [searchBarAccessory, children, actions] }));
30
27
  };
31
28
  const GridItem = ({ detail, actions, keywords, ...props }) => {
32
29
  const id = (0, react_1.useRef)(props.id ?? (0, crypto_1.randomUUID)());
@@ -7,16 +7,13 @@ const image_1 = require("../image");
7
7
  const crypto_1 = require("crypto");
8
8
  const metadata_1 = require("./metadata");
9
9
  const empty_view_1 = require("./empty-view");
10
- const hooks_1 = require("../hooks");
11
10
  const dropdown_1 = require("./dropdown");
12
- const ListRoot = ({ onSearchTextChange, searchBarAccessory, onSelectionChange, children, actions, ...props }) => {
13
- const searchTextChangeHandler = (0, hooks_1.useEventListener)(onSearchTextChange);
14
- const selectionChangeHandler = (0, hooks_1.useEventListener)(onSelectionChange);
11
+ const ListRoot = ({ searchBarAccessory, children, actions, ...props }) => {
15
12
  if (typeof props.enableFiltering === "boolean" &&
16
13
  typeof props.filtering === "undefined") {
17
14
  props.filtering = props.enableFiltering;
18
15
  }
19
- return ((0, jsx_runtime_1.jsxs)("list", { onSearchTextChange: searchTextChangeHandler, onSelectionChange: selectionChangeHandler, ...props, children: [searchBarAccessory, children, actions] }));
16
+ return ((0, jsx_runtime_1.jsxs)("list", { ...props, children: [searchBarAccessory, children, actions] }));
20
17
  };
21
18
  const ListItem = ({ detail, actions, ...props }) => {
22
19
  const id = (0, react_1.useRef)(props.id ?? (0, crypto_1.randomUUID)());
@@ -4,7 +4,6 @@ exports.TagList = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const image_1 = require("../image");
6
6
  const color_1 = require("../color");
7
- const hooks_1 = require("../hooks");
8
7
  const TagListRoot = ({ title, children }) => {
9
8
  const nativeProps = {
10
9
  title,
@@ -12,11 +11,10 @@ const TagListRoot = ({ title, children }) => {
12
11
  };
13
12
  return (0, jsx_runtime_1.jsx)("tag-list", { ...nativeProps });
14
13
  };
15
- const TagItem = ({ color, icon, text, onAction }) => {
16
- const onActionHandler = (0, hooks_1.useEventListener)(onAction);
14
+ const TagItem = ({ color, icon, text, ...props }) => {
17
15
  const nativeProps = {
16
+ ...props,
18
17
  text,
19
- onAction: onActionHandler,
20
18
  };
21
19
  if (color)
22
20
  nativeProps.color = (0, color_1.serializeColorLike)(color);
@@ -14,9 +14,10 @@ const View = ({ children }) => {
14
14
  const NavigationProvider = ({ root }) => {
15
15
  const [navStack, setNavStack] = (0, react_1.useState)([root]);
16
16
  const pop = () => {
17
- bus_1.bus.turboRequest("ui.popView", {}).then(() => {
18
- setNavStack((cur) => cur.slice(0, -1));
19
- });
17
+ // we ask Vicinae to pop the current view, but we need to wait
18
+ // for the pop-view event to be fired in order to dismount it from
19
+ // our local view stack: otherwise Vicinae might miss a render.
20
+ bus_1.bus.turboRequest("ui.popView", {});
20
21
  };
21
22
  const push = (node) => {
22
23
  bus_1.bus.turboRequest("ui.pushView", {}).then(() => {
@@ -1 +1 @@
1
- export declare const useEventListener: (fn: ((...args: any[]) => void) | undefined) => string | undefined;
1
+ export {};
package/dist/api/hooks.js CHANGED
@@ -1,26 +1,30 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useEventListener = void 0;
4
- const react_1 = require("react");
5
- const bus_1 = require("./bus");
6
3
  const handlerIdFactory = {
7
4
  nextHandlerId: 0,
8
5
  next() {
9
6
  return this.nextHandlerId++;
10
7
  },
11
8
  };
12
- const useEventListener = (fn) => {
13
- const id = (0, react_1.useRef)(`handler:${handlerIdFactory.next()}`);
14
- const callback = (0, react_1.useRef)();
15
- (0, react_1.useEffect)(() => {
16
- const { unsubscribe } = bus_1.bus.subscribe(id.current, (...args) => {
17
- callback.current?.(...args);
18
- });
19
- return unsubscribe;
20
- }, []);
21
- (0, react_1.useEffect)(() => {
22
- callback.current = fn;
23
- }, [fn]);
24
- return fn && id.current;
9
+ /*
10
+ export const useEventListener = (
11
+ fn: ((...args: any[]) => void) | undefined,
12
+ ) => {
13
+ const id = useRef(`handler:${handlerIdFactory.next()}`);
14
+ const callback = useRef<((...args: any[]) => void) | undefined>();
15
+
16
+ useEffect(() => {
17
+ const { unsubscribe } = bus.subscribe(id.current, (...args: any[]) => {
18
+ callback.current?.(...args);
19
+ });
20
+
21
+ return unsubscribe;
22
+ }, []);
23
+
24
+ useEffect(() => {
25
+ callback.current = fn;
26
+ }, [fn]);
27
+
28
+ return fn && id.current;
25
29
  };
26
- exports.useEventListener = useEventListener;
30
+ */
@@ -0,0 +1,36 @@
1
+ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
2
+ export declare const protobufPackage = "proto.ext.daemon";
3
+ export interface UrlResponse {
4
+ }
5
+ export interface UrlRequest {
6
+ url: string;
7
+ }
8
+ export interface Request {
9
+ url?: UrlRequest | undefined;
10
+ }
11
+ export interface Response {
12
+ url?: UrlResponse | undefined;
13
+ }
14
+ export declare const UrlResponse: MessageFns<UrlResponse>;
15
+ export declare const UrlRequest: MessageFns<UrlRequest>;
16
+ export declare const Request: MessageFns<Request>;
17
+ export declare const Response: MessageFns<Response>;
18
+ type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
19
+ export type DeepPartial<T> = T extends Builtin ? T : T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : T extends {} ? {
20
+ [K in keyof T]?: DeepPartial<T[K]>;
21
+ } : Partial<T>;
22
+ type KeysOfUnion<T> = T extends T ? keyof T : never;
23
+ export type Exact<P, I extends P> = P extends Builtin ? P : P & {
24
+ [K in keyof P]: Exact<P[K], I[K]>;
25
+ } & {
26
+ [K in Exclude<keyof I, KeysOfUnion<P>>]: never;
27
+ };
28
+ export interface MessageFns<T> {
29
+ encode(message: T, writer?: BinaryWriter): BinaryWriter;
30
+ decode(input: BinaryReader | Uint8Array, length?: number): T;
31
+ fromJSON(object: any): T;
32
+ toJSON(message: T): unknown;
33
+ create<I extends Exact<DeepPartial<T>, I>>(base?: I): T;
34
+ fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T;
35
+ }
36
+ export {};
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
3
+ // versions:
4
+ // protoc-gen-ts_proto v2.7.5
5
+ // protoc v6.31.1
6
+ // source: daemon.proto
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.Response = exports.Request = exports.UrlRequest = exports.UrlResponse = exports.protobufPackage = void 0;
9
+ /* eslint-disable */
10
+ const wire_1 = require("@bufbuild/protobuf/wire");
11
+ exports.protobufPackage = "proto.ext.daemon";
12
+ function createBaseUrlResponse() {
13
+ return {};
14
+ }
15
+ exports.UrlResponse = {
16
+ encode(_, writer = new wire_1.BinaryWriter()) {
17
+ return writer;
18
+ },
19
+ decode(input, length) {
20
+ const reader = input instanceof wire_1.BinaryReader ? input : new wire_1.BinaryReader(input);
21
+ const end = length === undefined ? reader.len : reader.pos + length;
22
+ const message = createBaseUrlResponse();
23
+ while (reader.pos < end) {
24
+ const tag = reader.uint32();
25
+ switch (tag >>> 3) {
26
+ }
27
+ if ((tag & 7) === 4 || tag === 0) {
28
+ break;
29
+ }
30
+ reader.skip(tag & 7);
31
+ }
32
+ return message;
33
+ },
34
+ fromJSON(_) {
35
+ return {};
36
+ },
37
+ toJSON(_) {
38
+ const obj = {};
39
+ return obj;
40
+ },
41
+ create(base) {
42
+ return exports.UrlResponse.fromPartial(base ?? {});
43
+ },
44
+ fromPartial(_) {
45
+ const message = createBaseUrlResponse();
46
+ return message;
47
+ },
48
+ };
49
+ function createBaseUrlRequest() {
50
+ return { url: "" };
51
+ }
52
+ exports.UrlRequest = {
53
+ encode(message, writer = new wire_1.BinaryWriter()) {
54
+ if (message.url !== "") {
55
+ writer.uint32(10).string(message.url);
56
+ }
57
+ return writer;
58
+ },
59
+ decode(input, length) {
60
+ const reader = input instanceof wire_1.BinaryReader ? input : new wire_1.BinaryReader(input);
61
+ const end = length === undefined ? reader.len : reader.pos + length;
62
+ const message = createBaseUrlRequest();
63
+ while (reader.pos < end) {
64
+ const tag = reader.uint32();
65
+ switch (tag >>> 3) {
66
+ case 1: {
67
+ if (tag !== 10) {
68
+ break;
69
+ }
70
+ message.url = reader.string();
71
+ continue;
72
+ }
73
+ }
74
+ if ((tag & 7) === 4 || tag === 0) {
75
+ break;
76
+ }
77
+ reader.skip(tag & 7);
78
+ }
79
+ return message;
80
+ },
81
+ fromJSON(object) {
82
+ return { url: isSet(object.url) ? globalThis.String(object.url) : "" };
83
+ },
84
+ toJSON(message) {
85
+ const obj = {};
86
+ if (message.url !== "") {
87
+ obj.url = message.url;
88
+ }
89
+ return obj;
90
+ },
91
+ create(base) {
92
+ return exports.UrlRequest.fromPartial(base ?? {});
93
+ },
94
+ fromPartial(object) {
95
+ const message = createBaseUrlRequest();
96
+ message.url = object.url ?? "";
97
+ return message;
98
+ },
99
+ };
100
+ function createBaseRequest() {
101
+ return { url: undefined };
102
+ }
103
+ exports.Request = {
104
+ encode(message, writer = new wire_1.BinaryWriter()) {
105
+ if (message.url !== undefined) {
106
+ exports.UrlRequest.encode(message.url, writer.uint32(10).fork()).join();
107
+ }
108
+ return writer;
109
+ },
110
+ decode(input, length) {
111
+ const reader = input instanceof wire_1.BinaryReader ? input : new wire_1.BinaryReader(input);
112
+ const end = length === undefined ? reader.len : reader.pos + length;
113
+ const message = createBaseRequest();
114
+ while (reader.pos < end) {
115
+ const tag = reader.uint32();
116
+ switch (tag >>> 3) {
117
+ case 1: {
118
+ if (tag !== 10) {
119
+ break;
120
+ }
121
+ message.url = exports.UrlRequest.decode(reader, reader.uint32());
122
+ continue;
123
+ }
124
+ }
125
+ if ((tag & 7) === 4 || tag === 0) {
126
+ break;
127
+ }
128
+ reader.skip(tag & 7);
129
+ }
130
+ return message;
131
+ },
132
+ fromJSON(object) {
133
+ return {
134
+ url: isSet(object.url) ? exports.UrlRequest.fromJSON(object.url) : undefined,
135
+ };
136
+ },
137
+ toJSON(message) {
138
+ const obj = {};
139
+ if (message.url !== undefined) {
140
+ obj.url = exports.UrlRequest.toJSON(message.url);
141
+ }
142
+ return obj;
143
+ },
144
+ create(base) {
145
+ return exports.Request.fromPartial(base ?? {});
146
+ },
147
+ fromPartial(object) {
148
+ const message = createBaseRequest();
149
+ message.url =
150
+ object.url !== undefined && object.url !== null
151
+ ? exports.UrlRequest.fromPartial(object.url)
152
+ : undefined;
153
+ return message;
154
+ },
155
+ };
156
+ function createBaseResponse() {
157
+ return { url: undefined };
158
+ }
159
+ exports.Response = {
160
+ encode(message, writer = new wire_1.BinaryWriter()) {
161
+ if (message.url !== undefined) {
162
+ exports.UrlResponse.encode(message.url, writer.uint32(10).fork()).join();
163
+ }
164
+ return writer;
165
+ },
166
+ decode(input, length) {
167
+ const reader = input instanceof wire_1.BinaryReader ? input : new wire_1.BinaryReader(input);
168
+ const end = length === undefined ? reader.len : reader.pos + length;
169
+ const message = createBaseResponse();
170
+ while (reader.pos < end) {
171
+ const tag = reader.uint32();
172
+ switch (tag >>> 3) {
173
+ case 1: {
174
+ if (tag !== 10) {
175
+ break;
176
+ }
177
+ message.url = exports.UrlResponse.decode(reader, reader.uint32());
178
+ continue;
179
+ }
180
+ }
181
+ if ((tag & 7) === 4 || tag === 0) {
182
+ break;
183
+ }
184
+ reader.skip(tag & 7);
185
+ }
186
+ return message;
187
+ },
188
+ fromJSON(object) {
189
+ return {
190
+ url: isSet(object.url) ? exports.UrlResponse.fromJSON(object.url) : undefined,
191
+ };
192
+ },
193
+ toJSON(message) {
194
+ const obj = {};
195
+ if (message.url !== undefined) {
196
+ obj.url = exports.UrlResponse.toJSON(message.url);
197
+ }
198
+ return obj;
199
+ },
200
+ create(base) {
201
+ return exports.Response.fromPartial(base ?? {});
202
+ },
203
+ fromPartial(object) {
204
+ const message = createBaseResponse();
205
+ message.url =
206
+ object.url !== undefined && object.url !== null
207
+ ? exports.UrlResponse.fromPartial(object.url)
208
+ : undefined;
209
+ return message;
210
+ },
211
+ };
212
+ function isSet(value) {
213
+ return value !== null && value !== undefined;
214
+ }
@@ -0,0 +1,30 @@
1
+ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
2
+ export declare const protobufPackage = "proto.ext.wlrclip";
3
+ export interface Offer {
4
+ data: Uint8Array;
5
+ mimeType: string;
6
+ }
7
+ export interface Selection {
8
+ offers: Offer[];
9
+ }
10
+ export declare const Offer: MessageFns<Offer>;
11
+ export declare const Selection: MessageFns<Selection>;
12
+ type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
13
+ export type DeepPartial<T> = T extends Builtin ? T : T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : T extends {} ? {
14
+ [K in keyof T]?: DeepPartial<T[K]>;
15
+ } : Partial<T>;
16
+ type KeysOfUnion<T> = T extends T ? keyof T : never;
17
+ export type Exact<P, I extends P> = P extends Builtin ? P : P & {
18
+ [K in keyof P]: Exact<P[K], I[K]>;
19
+ } & {
20
+ [K in Exclude<keyof I, KeysOfUnion<P>>]: never;
21
+ };
22
+ export interface MessageFns<T> {
23
+ encode(message: T, writer?: BinaryWriter): BinaryWriter;
24
+ decode(input: BinaryReader | Uint8Array, length?: number): T;
25
+ fromJSON(object: any): T;
26
+ toJSON(message: T): unknown;
27
+ create<I extends Exact<DeepPartial<T>, I>>(base?: I): T;
28
+ fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T;
29
+ }
30
+ export {};
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
3
+ // versions:
4
+ // protoc-gen-ts_proto v2.7.5
5
+ // protoc v6.31.1
6
+ // source: wlr-clipboard.proto
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.Selection = exports.Offer = exports.protobufPackage = void 0;
9
+ /* eslint-disable */
10
+ const wire_1 = require("@bufbuild/protobuf/wire");
11
+ exports.protobufPackage = "proto.ext.wlrclip";
12
+ function createBaseOffer() {
13
+ return { data: new Uint8Array(0), mimeType: "" };
14
+ }
15
+ exports.Offer = {
16
+ encode(message, writer = new wire_1.BinaryWriter()) {
17
+ if (message.data.length !== 0) {
18
+ writer.uint32(10).bytes(message.data);
19
+ }
20
+ if (message.mimeType !== "") {
21
+ writer.uint32(18).string(message.mimeType);
22
+ }
23
+ return writer;
24
+ },
25
+ decode(input, length) {
26
+ const reader = input instanceof wire_1.BinaryReader ? input : new wire_1.BinaryReader(input);
27
+ const end = length === undefined ? reader.len : reader.pos + length;
28
+ const message = createBaseOffer();
29
+ while (reader.pos < end) {
30
+ const tag = reader.uint32();
31
+ switch (tag >>> 3) {
32
+ case 1: {
33
+ if (tag !== 10) {
34
+ break;
35
+ }
36
+ message.data = reader.bytes();
37
+ continue;
38
+ }
39
+ case 2: {
40
+ if (tag !== 18) {
41
+ break;
42
+ }
43
+ message.mimeType = reader.string();
44
+ continue;
45
+ }
46
+ }
47
+ if ((tag & 7) === 4 || tag === 0) {
48
+ break;
49
+ }
50
+ reader.skip(tag & 7);
51
+ }
52
+ return message;
53
+ },
54
+ fromJSON(object) {
55
+ return {
56
+ data: isSet(object.data)
57
+ ? bytesFromBase64(object.data)
58
+ : new Uint8Array(0),
59
+ mimeType: isSet(object.mimeType)
60
+ ? globalThis.String(object.mimeType)
61
+ : "",
62
+ };
63
+ },
64
+ toJSON(message) {
65
+ const obj = {};
66
+ if (message.data.length !== 0) {
67
+ obj.data = base64FromBytes(message.data);
68
+ }
69
+ if (message.mimeType !== "") {
70
+ obj.mimeType = message.mimeType;
71
+ }
72
+ return obj;
73
+ },
74
+ create(base) {
75
+ return exports.Offer.fromPartial(base ?? {});
76
+ },
77
+ fromPartial(object) {
78
+ const message = createBaseOffer();
79
+ message.data = object.data ?? new Uint8Array(0);
80
+ message.mimeType = object.mimeType ?? "";
81
+ return message;
82
+ },
83
+ };
84
+ function createBaseSelection() {
85
+ return { offers: [] };
86
+ }
87
+ exports.Selection = {
88
+ encode(message, writer = new wire_1.BinaryWriter()) {
89
+ for (const v of message.offers) {
90
+ exports.Offer.encode(v, writer.uint32(10).fork()).join();
91
+ }
92
+ return writer;
93
+ },
94
+ decode(input, length) {
95
+ const reader = input instanceof wire_1.BinaryReader ? input : new wire_1.BinaryReader(input);
96
+ const end = length === undefined ? reader.len : reader.pos + length;
97
+ const message = createBaseSelection();
98
+ while (reader.pos < end) {
99
+ const tag = reader.uint32();
100
+ switch (tag >>> 3) {
101
+ case 1: {
102
+ if (tag !== 10) {
103
+ break;
104
+ }
105
+ message.offers.push(exports.Offer.decode(reader, reader.uint32()));
106
+ continue;
107
+ }
108
+ }
109
+ if ((tag & 7) === 4 || tag === 0) {
110
+ break;
111
+ }
112
+ reader.skip(tag & 7);
113
+ }
114
+ return message;
115
+ },
116
+ fromJSON(object) {
117
+ return {
118
+ offers: globalThis.Array.isArray(object?.offers)
119
+ ? object.offers.map((e) => exports.Offer.fromJSON(e))
120
+ : [],
121
+ };
122
+ },
123
+ toJSON(message) {
124
+ const obj = {};
125
+ if (message.offers?.length) {
126
+ obj.offers = message.offers.map((e) => exports.Offer.toJSON(e));
127
+ }
128
+ return obj;
129
+ },
130
+ create(base) {
131
+ return exports.Selection.fromPartial(base ?? {});
132
+ },
133
+ fromPartial(object) {
134
+ const message = createBaseSelection();
135
+ message.offers = object.offers?.map((e) => exports.Offer.fromPartial(e)) || [];
136
+ return message;
137
+ },
138
+ };
139
+ function bytesFromBase64(b64) {
140
+ if (globalThis.Buffer) {
141
+ return Uint8Array.from(globalThis.Buffer.from(b64, "base64"));
142
+ }
143
+ else {
144
+ const bin = globalThis.atob(b64);
145
+ const arr = new Uint8Array(bin.length);
146
+ for (let i = 0; i < bin.length; ++i) {
147
+ arr[i] = bin.charCodeAt(i);
148
+ }
149
+ return arr;
150
+ }
151
+ }
152
+ function base64FromBytes(arr) {
153
+ if (globalThis.Buffer) {
154
+ return globalThis.Buffer.from(arr).toString("base64");
155
+ }
156
+ else {
157
+ const bin = [];
158
+ arr.forEach((byte) => {
159
+ bin.push(globalThis.String.fromCharCode(byte));
160
+ });
161
+ return globalThis.btoa(bin.join(""));
162
+ }
163
+ }
164
+ function isSet(value) {
165
+ return value !== null && value !== undefined;
166
+ }
package/dist/api/toast.js CHANGED
@@ -43,13 +43,15 @@ class Toast {
43
43
  };
44
44
  if (props.primaryAction) {
45
45
  const { onAction } = props.primaryAction;
46
+ const { id } = bus_1.bus.addEventHandler(() => onAction(this));
46
47
  this.options.primaryAction = props.primaryAction;
47
- this.callbacks.primary = (0, bus_1.createHandler)(() => onAction(this));
48
+ this.callbacks.primary = id;
48
49
  }
49
50
  if (props.secondaryAction) {
50
51
  const { onAction } = props.secondaryAction;
52
+ const { id } = bus_1.bus.addEventHandler(() => onAction(this));
51
53
  this.options.secondaryAction = props.secondaryAction;
52
- this.callbacks.secondary = (0, bus_1.createHandler)(() => onAction(this));
54
+ this.callbacks.secondary = id;
53
55
  }
54
56
  }
55
57
  /**
@@ -67,17 +67,20 @@ class Develop extends core_1.Command {
67
67
  const { flags } = await this.parse(Develop);
68
68
  const logger = new logger_js_1.Logger();
69
69
  const pkgPath = (0, node_path_1.join)(flags.target, "package.json");
70
- if (!(0, node_fs_1.existsSync)(pkgPath)) {
71
- logger.logError(`No package.json found at ${pkgPath}. Does this location point to a valid extension repository?`);
72
- process.exit(1);
73
- }
74
- const json = JSON.parse((0, node_fs_1.readFileSync)(pkgPath, "utf8"));
75
- const e = manifest_js_1.default.safeParse(json);
76
- if (e.error) {
77
- logger.logError(`${pkgPath} is not a valid extension manifest: ${e.error}`);
78
- process.exit(1);
79
- }
80
- const manifest = e.data;
70
+ const parseManifest = () => {
71
+ if (!(0, node_fs_1.existsSync)(pkgPath)) {
72
+ logger.logError(`No package.json found at ${pkgPath}. Does this location point to a valid extension repository?`);
73
+ process.exit(1);
74
+ }
75
+ const json = JSON.parse((0, node_fs_1.readFileSync)(pkgPath, "utf8"));
76
+ const e = manifest_js_1.default.safeParse(json);
77
+ if (e.error) {
78
+ logger.logError(`${pkgPath} is not a valid extension manifest: ${e.error}`);
79
+ process.exit(1);
80
+ }
81
+ return e.data;
82
+ };
83
+ let manifest = parseManifest();
81
84
  const vicinae = new vicinae_js_1.VicinaeClient();
82
85
  const typeCheck = async () => {
83
86
  const spawned = (0, node_child_process_1.spawn)("npx", ["tsc", "--noEmit"]);
@@ -90,14 +93,17 @@ class Develop extends core_1.Command {
90
93
  });
91
94
  };
92
95
  const build = async (outDir) => {
96
+ /*
93
97
  logger.logInfo("Started type checking in background thread");
94
98
  typeCheck().then(({ error, ok }) => {
95
- if (!ok) {
96
- logger.logInfo(`Type checking error: ${error}`);
97
- }
98
- logger.logInfo("Done type checking");
99
+ if (!ok) {
100
+ logger.logInfo(`Type checking error: ${error}`);
101
+ }
102
+
103
+ logger.logInfo("Done type checking");
99
104
  });
100
- const entryPoints = manifest.commands.map((cmd) => (0, node_path_1.join)("src", `${cmd.name}.tsx`));
105
+ */
106
+ const entryPoints = manifest.commands.map((cmd) => (0, node_path_1.join)("src", `${cmd.name}.tsx`)).filter(node_fs_1.existsSync);
101
107
  logger.logInfo(`entrypoints [${entryPoints.join(", ")}]`);
102
108
  const promises = manifest.commands.map((cmd) => {
103
109
  const base = (0, node_path_1.join)(process.cwd(), "src", `${cmd.name}`);
@@ -105,14 +111,14 @@ class Develop extends core_1.Command {
105
111
  const tsSource = `${base}.ts`;
106
112
  let source = tsxSource;
107
113
  if (cmd.mode == "view" && !(0, node_fs_1.existsSync)(tsxSource)) {
108
- throw new Error(`Unable to find view command ${cmd.name} at ${tsxSource}`);
114
+ throw new Error(`could not find entrypoint src/${cmd.name}.tsx for command ${cmd.name}.`);
109
115
  }
110
116
  // we allow .ts or .tsx for no-view
111
117
  if (cmd.mode == "no-view") {
112
118
  if (!(0, node_fs_1.existsSync)(tsxSource)) {
113
119
  source = tsSource;
114
120
  if (!(0, node_fs_1.existsSync)(tsSource)) {
115
- throw new Error(`Unable to find no-view command ${cmd.name} at ${base}.{ts,tsx}`);
121
+ throw new Error(`could not find entrypoint src/${cmd.name}.{ts,tsx} for command ${cmd.name}.`);
116
122
  }
117
123
  }
118
124
  }
@@ -141,6 +147,23 @@ class Develop extends core_1.Command {
141
147
  console.error(`Failed to ping vicinae\n`, pingError.message);
142
148
  return;
143
149
  }
150
+ const safeBuild = async (extensionDir) => {
151
+ try {
152
+ const start = performance.now();
153
+ await build(extensionDir);
154
+ const time = performance.now() - start;
155
+ logger.logReady(`Extension built in ${Math.round(time)}ms 🚀`);
156
+ vicinae.refreshDevSession(id);
157
+ }
158
+ catch (error) {
159
+ if (error instanceof Error) {
160
+ logger.logError(`Failed to build extension: ${error.message}`);
161
+ }
162
+ else {
163
+ logger.logError(`Failed to build extension: ${error}`);
164
+ }
165
+ }
166
+ };
144
167
  process.chdir(flags.target);
145
168
  const dataDir = (0, utils_js_1.extensionDataDir)();
146
169
  const id = `${manifest.name}`;
@@ -148,10 +171,9 @@ class Develop extends core_1.Command {
148
171
  const logFile = (0, node_path_1.join)(extensionDir, "dev.log");
149
172
  const pidFile = (0, node_path_1.join)(extensionDir, "cli.pid");
150
173
  (0, node_fs_1.mkdirSync)(extensionDir, { recursive: true });
151
- await build(extensionDir);
152
- logger.logReady("built extension successfully");
153
174
  (0, node_fs_1.writeFileSync)(pidFile, `${process.pid}`);
154
175
  (0, node_fs_1.writeFileSync)(logFile, "");
176
+ await safeBuild(extensionDir);
155
177
  process.on("SIGINT", () => {
156
178
  logger.logInfo("Shutting down...");
157
179
  vicinae.stopDevSession(id);
@@ -167,16 +189,12 @@ class Develop extends core_1.Command {
167
189
  awaitWriteFinish: { pollInterval: 100, stabilityThreshold: 100 },
168
190
  ignoreInitial: true,
169
191
  })
170
- .on("all", (_, path) => {
171
- logger.logEvent(`changed file ${path}:`);
172
- try {
173
- build(extensionDir);
174
- logger.logReady("built extension successfully");
175
- vicinae.refreshDevSession(id);
176
- }
177
- catch (error) {
178
- logger.logEvent(`Failed to build extension: ${error}`);
192
+ .on("all", async (_, path) => {
193
+ if (path.endsWith('package.json')) {
194
+ manifest = parseManifest();
179
195
  }
196
+ logger.logEvent(`changed file ${path}`);
197
+ await safeBuild(extensionDir);
180
198
  });
181
199
  const logFiles = new Map();
182
200
  chokidar.watch(logFile).on("all", async (_, path) => {
@@ -184,7 +202,7 @@ class Develop extends core_1.Command {
184
202
  if (!stats.isFile())
185
203
  return;
186
204
  if (!logFiles.has(path)) {
187
- logger.logInfo(`Monitoring new log file at ${path}`);
205
+ //logger.logInfo(`Monitoring new log file at ${path}`);
188
206
  logFiles.set(path, { cursor: 0, path });
189
207
  }
190
208
  const info = logFiles.get(path);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vicinae/api",
3
- "version": "0.8.2",
3
+ "version": "0.8.4",
4
4
  "description": "TypeScript SDK to build Vicinae extensions",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -29,8 +29,8 @@
29
29
  "@oclif/core": "^4",
30
30
  "@oclif/plugin-help": "^6",
31
31
  "@oclif/plugin-plugins": "^5",
32
- "@types/react": "^18.1.0",
33
32
  "@types/node": ">=18",
33
+ "@types/react": "^18.1.0",
34
34
  "chalk": "^5.6.0",
35
35
  "chokidar": "^4.0.3",
36
36
  "esbuild": "^0.25.2",
package/types/jsx.d.ts ADDED
@@ -0,0 +1,178 @@
1
+ import * as React from "react";
2
+
3
+ import type { ListItemDetailProps } from "../api/components/list";
4
+ import { SerializedImageLike } from "../api/image";
5
+ import { SerializedColorLike } from "../api/color";
6
+ import { Keyboard } from "../api/keyboard";
7
+ import { Grid } from "../api/components/grid";
8
+
9
+ import 'react';
10
+
11
+ declare module "react" {
12
+ namespace JSX {
13
+ interface IntrinsicElements {
14
+ detail: {
15
+ navigationTitle?: string;
16
+ markdown: string;
17
+ };
18
+ list: {
19
+ children?: React.ReactNode;
20
+ filtering?: boolean;
21
+ isLoading?: boolean;
22
+ isShowingDetail?: boolean;
23
+ searchBarPlaceholder?: string;
24
+ navigationTitle?: string;
25
+ onSearchTextChange?: (text: string) => void;
26
+ onSelectionChange?: (selectedItemId: string) => void;
27
+ };
28
+ "list-section": {
29
+ title?: string;
30
+ subtitle?: string;
31
+ children?: React.ReactNode;
32
+ };
33
+ "list-item": {
34
+ title: string;
35
+ id?: string;
36
+ subtitle?: string;
37
+ icon?: SerializedImageLike;
38
+ keywords?: string[];
39
+ };
40
+ "list-item-detail": ListItemDetailProps;
41
+ "list-item-detail-metadata": any;
42
+ "list-accessory": {};
43
+
44
+ grid: {
45
+ inset?: Grid.Inset;
46
+ columns?: number;
47
+ fit: Grid.Fit;
48
+ aspectRatio: Grid.AspectRatio;
49
+
50
+ children?: React.ReactNode;
51
+ filtering?: boolean;
52
+ isLoading?: boolean;
53
+ isShowingDetail?: boolean;
54
+ searchBarPlaceholder?: string;
55
+ navigationTitle?: string;
56
+ onSearchTextChange?: (text: string) => void;
57
+ onSelectionChange?: (selectedItemId: string) => void;
58
+ };
59
+ "grid-section": {
60
+ inset?: Grid.Inset;
61
+ columns?: number;
62
+ fit: Grid.Fit;
63
+ aspectRatio: Grid.AspectRatio;
64
+
65
+ title?: string;
66
+ subtitle?: string;
67
+ children?: React.ReactNode;
68
+ };
69
+ "grid-item": {
70
+ title?: string;
71
+ id?: string;
72
+ subtitle?: string;
73
+ content?: SerializedImageLike | { color: ColorLike } | { value: SerializedImageLike, tooltip?: string };
74
+ keywords?: string[];
75
+ };
76
+
77
+ "empty-view": {
78
+ description?: string;
79
+ title?: string;
80
+ icon?: SerializedImageLike;
81
+ };
82
+ metadata: {
83
+ children?: React.ReactNode;
84
+ };
85
+ "metadata-label": {
86
+ title: string;
87
+ text: string;
88
+ icon?: SerializedImageLike;
89
+ };
90
+ "metadata-separator": {};
91
+ "metadata-link": {
92
+ title: string;
93
+ target: string;
94
+ text: string;
95
+ };
96
+ "action-panel": {
97
+ title?: string;
98
+ children?: React.ReactNode;
99
+ };
100
+ "action-panel-submenu": {
101
+ title: string;
102
+ icon?: SerializedImageLike;
103
+ onOpen?: () => void;
104
+ onSearchTextChange?: (text: string) => void;
105
+ children?: React.ReactNode;
106
+ };
107
+ "action-panel-section": {
108
+ title?: string;
109
+ children?: React.ReactNode;
110
+ };
111
+ action: {
112
+ title: string;
113
+ onAction: () => void;
114
+ onSubmit?: Function;
115
+ shortcut?: Keyboard.Shortcut;
116
+ icon?: SerializedImageLike;
117
+ autoFocus?: boolean;
118
+ };
119
+ "tag-list": {
120
+ title?: string;
121
+ children?: React.ReactNode;
122
+ };
123
+ "tag-item": {
124
+ color?: SerializedColorLike;
125
+ icon?: SerializedImageLike;
126
+ text?: string;
127
+ onAction?: () => void;
128
+ };
129
+ form: {
130
+ enableDrafts: boolean;
131
+ isLoading: boolean;
132
+ navigationTitle?: string;
133
+ children?: React.ReactNode;
134
+ };
135
+ "text-field": {
136
+ onBlur?: Function;
137
+ onFocus?: Function;
138
+ onChange?: Function;
139
+ };
140
+ "dropdown-field": {
141
+ onBlur?: Function;
142
+ onFocus?: Function;
143
+ onChange?: Function;
144
+ children?: ReactNode;
145
+ };
146
+ "date-picker-field": {};
147
+ "checkbox-field": {
148
+ onBlur?: Function;
149
+ onFocus?: Function;
150
+ onChange?: Function;
151
+ };
152
+ "password-field": {};
153
+ "textarea-field": {};
154
+
155
+ dropdown: {
156
+ onChange?: Function;
157
+ onSearchTextChange?: (text: string) => void;
158
+ children?: ReactNode;
159
+ };
160
+ "dropdown-section": {
161
+ title?: string;
162
+ children: ReactNode;
163
+ };
164
+ "dropdown-item": {
165
+ title: string;
166
+ value: string;
167
+ icon?: SerializedImageLike;
168
+ keywords?: string[];
169
+ };
170
+
171
+ separator: {};
172
+ "menu-bar": {};
173
+ "menu-bar-item": {};
174
+ "menu-bar-submenu": {};
175
+ "menu-bar-section": {};
176
+ }
177
+ }
178
+ }