@preset.nz/app-kit 0.1.1 → 0.1.2

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
@@ -96,4 +96,4 @@ In Vite, add `@preset.nz/app-kit` (with `react`, `react-dom`, `@tauri-apps/api`,
96
96
 
97
97
  ## Development
98
98
 
99
- `just check` runs `cargo fmt --check`, clippy, `cargo test`, `tsc` and eslint. MIT.
99
+ `just check` runs `cargo fmt --check`, clippy, `cargo test`, `tsc` and Biome. MIT.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@preset.nz/app-kit",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "The behaviour of a preset.nz desktop app: command table, menu sync, Undo and Redo titles, text-field undo routing and a selection store, over the preset-app-kit Rust crate.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -22,19 +22,15 @@
22
22
  "react": "^19"
23
23
  },
24
24
  "devDependencies": {
25
- "@eslint/js": "^9.39.4",
25
+ "@biomejs/biome": "^2.5.15",
26
26
  "@preset.nz/ux-kit": "^0.1.0",
27
27
  "@tauri-apps/api": "^2.11.1",
28
28
  "@types/react": "^19.2.17",
29
29
  "@types/react-dom": "^19.2.3",
30
- "eslint": "^9.39.4",
31
- "eslint-plugin-react-hooks": "^7.1.1",
32
- "eslint-plugin-react-refresh": "^0.5.3",
33
- "globals": "^16.5.0",
30
+ "lefthook": "^2.1.17",
34
31
  "react": "^19.2.7",
35
32
  "react-dom": "^19.2.7",
36
- "typescript": "~5.9.3",
37
- "typescript-eslint": "^8.61.1"
33
+ "typescript": "~5.9.3"
38
34
  },
39
35
  "peerDependenciesMeta": {
40
36
  "@preset.nz/ux-kit": {
@@ -1,10 +1,13 @@
1
- import type { ComponentProps } from "react"
2
1
  import { ToolbarItems } from "@preset.nz/ux-kit"
2
+ import type { ComponentProps } from "react"
3
3
 
4
4
  import type { Command } from "./commands"
5
- import { toItems, type ToolbarLayout } from "./toolbar"
5
+ import { type ToolbarLayout, toItems } from "./toolbar"
6
6
 
7
- type Props = Omit<ComponentProps<typeof ToolbarItems>, "groups" | "leading" | "trailing" | "onCommand"> & {
7
+ type Props = Omit<
8
+ ComponentProps<typeof ToolbarItems>,
9
+ "groups" | "leading" | "trailing" | "onCommand"
10
+ > & {
8
11
  commands: Command[]
9
12
  layout: ToolbarLayout
10
13
  /** From `useCommands`: runs the command the menu would. */
@@ -1,7 +1,7 @@
1
- import { useCallback, useEffect, useMemo, useState, type ReactNode } from "react"
2
1
  import { invoke } from "@tauri-apps/api/core"
2
+ import { type ReactNode, useCallback, useEffect, useMemo, useState } from "react"
3
3
 
4
- import { redo, undo, useHistory, type HistoryState } from "./history"
4
+ import { type HistoryState, redo, undo, useHistory } from "./history"
5
5
  import { useTextUndo } from "./text"
6
6
  import { useMenuSync } from "./useMenuSync"
7
7
 
@@ -133,6 +133,9 @@ export function useCommands(bindings: Record<string, Binding>) {
133
133
  [commands],
134
134
  )
135
135
  /** A command's display shortcut, for anything that shows one (a panel header's tooltip). */
136
- const shortcut = useCallback((id: string) => table?.find((s) => s.id === id)?.shortcut ?? undefined, [table])
136
+ const shortcut = useCallback(
137
+ (id: string) => table?.find((s) => s.id === id)?.shortcut ?? undefined,
138
+ [table],
139
+ )
137
140
  return { commands, run, shortcut, history }
138
141
  }
package/src-ts/core.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  // The menu half of app-kit: commands, history, text-field undo, selection and stores, with
2
2
  // no dependency on ux-kit. `index.ts` adds the toolbar bridge on top.
3
3
  export {
4
- bindCommands,
5
- useCommands,
6
- useCommandTable,
7
4
  type Binding,
5
+ bindCommands,
8
6
  type Command,
9
7
  type CommandSpec,
8
+ useCommands,
9
+ useCommandTable,
10
10
  } from "./commands"
11
- export { useDocument, useDocumentNotes, type DocumentState } from "./document"
12
- export { redo, undo, useHistory, type HistoryState } from "./history"
11
+ export { type DocumentState, useDocument, useDocumentNotes } from "./document"
12
+ export { type HistoryState, redo, undo, useHistory } from "./history"
13
13
  export { nativeContextMenu } from "./nativeContextMenu"
14
14
  export {
15
15
  createMultiSelection,
@@ -18,6 +18,6 @@ export {
18
18
  type MultiSelection,
19
19
  type Selection,
20
20
  } from "./selection"
21
- export { createStore, useStore, type Store } from "./store"
21
+ export { createStore, type Store, useStore } from "./store"
22
22
  export { blurField, isTextField, useTextFocus, useTextUndo } from "./text"
23
23
  export { useMenuSync } from "./useMenuSync"
@@ -1,6 +1,6 @@
1
- import { useEffect, useRef, useState } from "react"
2
1
  import { invoke } from "@tauri-apps/api/core"
3
2
  import { listen } from "@tauri-apps/api/event"
3
+ import { useEffect, useRef, useState } from "react"
4
4
 
5
5
  /** The document as Rust reports it (`DocumentState`): from `app_kit_document`, pushed as `app-kit://document`. */
6
6
  export interface DocumentState {
@@ -47,7 +47,9 @@ export function useDocumentNotes(onNote: (message: string) => void): void {
47
47
  // while still mounted: taking them is once-only, so an unmounted effect (StrictMode mounts
48
48
  // twice in dev) must leave them for the next.
49
49
  un.then(() => (live ? invoke<string[]>("app_kit_document_note") : [])).then(
50
- (held) => live && held.forEach((m) => handler.current(m)),
50
+ (held) => {
51
+ if (live) for (const m of held) handler.current(m)
52
+ },
51
53
  () => {},
52
54
  )
53
55
  return () => {
package/src-ts/history.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { useEffect, useState } from "react"
2
1
  import { invoke } from "@tauri-apps/api/core"
3
2
  import { listen } from "@tauri-apps/api/event"
3
+ import { useEffect, useState } from "react"
4
4
 
5
5
  import { blurField } from "./text"
6
6
 
package/src-ts/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  // Everything: the core plus the ux-kit toolbar bridge. Apps without ux-kit import
2
2
  // "@preset.nz/app-kit/core" instead.
3
- export * from "./core"
3
+
4
4
  export { CommandToolbar } from "./CommandToolbar"
5
- export { toItems, type ToolbarLayout } from "./toolbar"
5
+ export * from "./core"
6
+ export { type ToolbarLayout, toItems } from "./toolbar"
package/src-ts/store.ts CHANGED
@@ -15,7 +15,7 @@ export function createStore<T>(initial: T): Store<T> {
15
15
  set(next) {
16
16
  if (Object.is(next, state)) return
17
17
  state = next
18
- listeners.forEach((l) => l())
18
+ for (const l of listeners) l()
19
19
  },
20
20
  subscribe(l) {
21
21
  listeners.add(l)
package/src-ts/text.ts CHANGED
@@ -1,13 +1,23 @@
1
- import { useEffect, useState } from "react"
2
1
  import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow"
2
+ import { useEffect, useState } from "react"
3
3
 
4
- const TEXT_INPUT_TYPES = new Set(["", "text", "search", "url", "email", "tel", "password", "number"])
4
+ const TEXT_INPUT_TYPES = new Set([
5
+ "",
6
+ "text",
7
+ "search",
8
+ "url",
9
+ "email",
10
+ "tel",
11
+ "password",
12
+ "number",
13
+ ])
5
14
 
6
15
  /** True for elements that have their own typing undo: text inputs, textareas, contenteditable. */
7
16
  export function isTextField(el: EventTarget | Element | null): boolean {
8
17
  if (!(el instanceof HTMLElement)) return false
9
18
  if (el instanceof HTMLTextAreaElement) return !el.readOnly && !el.disabled
10
- if (el instanceof HTMLInputElement) return TEXT_INPUT_TYPES.has(el.type) && !el.readOnly && !el.disabled
19
+ if (el instanceof HTMLInputElement)
20
+ return TEXT_INPUT_TYPES.has(el.type) && !el.readOnly && !el.disabled
11
21
  return el.isContentEditable
12
22
  }
13
23
 
@@ -1,6 +1,6 @@
1
- import { useEffect, useRef } from "react"
2
1
  import { invoke } from "@tauri-apps/api/core"
3
2
  import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow"
3
+ import { useEffect, useRef } from "react"
4
4
 
5
5
  import type { Command } from "./commands"
6
6
 
@@ -31,12 +31,11 @@ export function useMenuSync(commands: Command[], textFocus: boolean) {
31
31
  }, [])
32
32
 
33
33
  const key = JSON.stringify(commands.map((c) => [c.id, c.enabled, c.pressed])) + textFocus
34
+ // biome-ignore lint/correctness/useExhaustiveDependencies: `key` stands for the commands' menu-relevant state (and textFocus); `latest` holds the commands themselves.
34
35
  useEffect(() => {
35
36
  const states = latest.current
36
37
  .filter((c) => !RUST_GATED_IDS.has(c.id))
37
38
  .map((c) => ({ id: c.id, enabled: c.enabled, checked: c.pressed }))
38
39
  invoke("app_kit_menu_state", { states, textFocus }).catch(() => {})
39
- // `key` stands for the commands' menu-relevant state; `latest` holds the commands.
40
- // eslint-disable-next-line react-hooks/exhaustive-deps
41
40
  }, [key])
42
41
  }