@toolpath/app-support 0.1.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/LICENSE +21 -0
- package/README.md +87 -0
- package/dist/chunk-YPOB3BBR.js +13 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +8 -0
- package/dist/react/index.d.ts +24 -0
- package/dist/react/index.js +21 -0
- package/package.json +66 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Toolpath
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Toolpath App Support
|
|
2
|
+
|
|
3
|
+
`@toolpath/app-support` is the logic a Toolpath application reuses: the
|
|
4
|
+
preferences, contexts and route helpers every application was otherwise going
|
|
5
|
+
to write for itself, and did.
|
|
6
|
+
|
|
7
|
+
**It renders nothing.** `@toolpath/ui` is the component kit — styling and
|
|
8
|
+
display, the surface documented in
|
|
9
|
+
[Storybook](https://storybook.staging.toolpath.com). This package is the other
|
|
10
|
+
half. Neither depends on the other, and that is the point: a preference read by
|
|
11
|
+
a loader on a server has no business pulling in a Tailwind component kit, and a
|
|
12
|
+
button has no business knowing where a preference is stored.
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
@toolpath/tool-support depends on nothing
|
|
16
|
+
↑
|
|
17
|
+
@toolpath/app-support the logic ─┐
|
|
18
|
+
├─ your application
|
|
19
|
+
@toolpath/ui the components ─┘
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npm install @toolpath/app-support react react-dom
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`react` and `react-dom` are peer dependencies, needed only for the `/react`
|
|
29
|
+
subpath.
|
|
30
|
+
|
|
31
|
+
## Two entry points
|
|
32
|
+
|
|
33
|
+
`@toolpath/app-support` imports no React. A preference is read by a loader on a
|
|
34
|
+
server as often as by a component in a browser, so the half that does not need
|
|
35
|
+
React does not import it.
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { loadUnit, saveUnit } from '@toolpath/app-support'
|
|
39
|
+
|
|
40
|
+
const unit = loadUnit(globalThis.localStorage ?? null, 'catalog.unit')
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`@toolpath/app-support/react` is the hooks and contexts.
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { useUnit } from '@toolpath/app-support/react'
|
|
47
|
+
|
|
48
|
+
export const UnitToggle = () => {
|
|
49
|
+
const [unit, choose] = useUnit('catalog.unit')
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<button type="button" onClick={() => choose(unit === 'inches' ? 'millimeters' : 'inches')}>
|
|
53
|
+
{unit}
|
|
54
|
+
</button>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## The unit a person reads in
|
|
60
|
+
|
|
61
|
+
The unit belongs to the person rather than to the thing being looked at: a
|
|
62
|
+
machinist works in one of them all day and should not set it again after
|
|
63
|
+
opening a report or a catalog.
|
|
64
|
+
|
|
65
|
+
- **The storage and the key are the caller's.** Passing the storage in is what
|
|
66
|
+
lets this be called on a server or in a test without a `window`. Taking the
|
|
67
|
+
key means two applications on one origin hold their own units instead of
|
|
68
|
+
silently sharing one.
|
|
69
|
+
- **`loadUnit` reads the older `'in'` spelling as well as `'inches'`.** Those
|
|
70
|
+
values are in people's browsers now, and a reader that accepts only the
|
|
71
|
+
current spelling moves every inch shop to metric the day it deploys.
|
|
72
|
+
- **`useUnit` opens on millimetres and reads the stored preference on the first
|
|
73
|
+
effect**, so a server render and its hydration agree instead of flashing the
|
|
74
|
+
wrong numbers.
|
|
75
|
+
|
|
76
|
+
The vocabulary is `@toolpath/tool-support`'s `UnitSystem`, which is this
|
|
77
|
+
package's one runtime dependency.
|
|
78
|
+
|
|
79
|
+
## Where this came from
|
|
80
|
+
|
|
81
|
+
`loadUnit`, `saveUnit` and `useUnit` shipped in `@toolpath/ui` 0.2.0 and 0.3.0.
|
|
82
|
+
That was the wrong package: the component kit is styling and display, and
|
|
83
|
+
storage policy is neither. They live here from `@toolpath/ui` 1.0.0 onward.
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
MIT
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// src/unit-preference.ts
|
|
2
|
+
var loadUnit = (storage, key) => {
|
|
3
|
+
const stored = storage?.getItem(key);
|
|
4
|
+
return stored === "inches" || stored === "in" ? "inches" : "millimeters";
|
|
5
|
+
};
|
|
6
|
+
var saveUnit = (storage, key, unit) => {
|
|
7
|
+
storage?.setItem(key, unit);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
loadUnit,
|
|
12
|
+
saveUnit
|
|
13
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { UnitSystem } from '@toolpath/tool-support';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The unit a person reads in, remembered between visits.
|
|
5
|
+
*
|
|
6
|
+
* It belongs to the person rather than to the thing being looked at: a
|
|
7
|
+
* machinist works in one of them all day and should not set it again after
|
|
8
|
+
* opening a report or a catalog.
|
|
9
|
+
*
|
|
10
|
+
* The storage is the caller's, so this can be called in a test or on a server
|
|
11
|
+
* without a `window`, and the key is the caller's too. Two applications on one
|
|
12
|
+
* origin would otherwise silently share the preference — defensible, but a
|
|
13
|
+
* decision each application should make rather than inherit from a constant it
|
|
14
|
+
* cannot see.
|
|
15
|
+
*
|
|
16
|
+
* The vocabulary is `@toolpath/tool-support`'s {@link UnitSystem}, imported
|
|
17
|
+
* rather than restated. Which system a person reads in and which system a
|
|
18
|
+
* vendor published a tool in are the same two values, and a second spelling of
|
|
19
|
+
* them is the lookup table that package exists to have removed.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* The stored unit, defaulting to millimetres — what Toolpath states every
|
|
23
|
+
* length in.
|
|
24
|
+
*
|
|
25
|
+
* **`'in'` is read as well as `'inches'`.** The preference was written under
|
|
26
|
+
* the short spelling for as long as that was the vocabulary, and those values
|
|
27
|
+
* are in people's browsers now. A reader that accepts only the current
|
|
28
|
+
* spelling silently moves every inch shop to metric the day it deploys.
|
|
29
|
+
*/
|
|
30
|
+
declare const loadUnit: (storage: Pick<Storage, "getItem"> | null, key: string) => UnitSystem;
|
|
31
|
+
/** Writes the current spelling. {@link loadUnit} still reads the old one. */
|
|
32
|
+
declare const saveUnit: (storage: Pick<Storage, "setItem"> | null, key: string, unit: UnitSystem) => void;
|
|
33
|
+
|
|
34
|
+
export { loadUnit, saveUnit };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { UnitSystem } from '@toolpath/tool-support';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The unit a person reads in, as a piece of React state.
|
|
5
|
+
*
|
|
6
|
+
* {@link loadUnit} and {@link saveUnit} are the storage; this is the three
|
|
7
|
+
* lines of React that every consumer of them was otherwise going to write. Two
|
|
8
|
+
* applications in the Toolpath template had written it, character for
|
|
9
|
+
* character, differing only in the key — which is the copy this exists to stop
|
|
10
|
+
* being made a third time.
|
|
11
|
+
*
|
|
12
|
+
* **The key is the caller's**, for the reason `unit-preference.ts` gives: two
|
|
13
|
+
* applications on one origin must be able to hold different units, and that is
|
|
14
|
+
* a decision each of them makes rather than inherits.
|
|
15
|
+
*
|
|
16
|
+
* **Read after mount rather than during render.** A server has no
|
|
17
|
+
* `localStorage`, so reading one while rendering makes the first paint depend
|
|
18
|
+
* on a browser that is not there yet — and a value that differed between the
|
|
19
|
+
* two hydrates as a flash of the wrong numbers. The opening state is therefore
|
|
20
|
+
* always millimetres, and the stored preference arrives on the first effect.
|
|
21
|
+
*/
|
|
22
|
+
declare const useUnit: (key: string) => [UnitSystem, (next: UnitSystem) => void];
|
|
23
|
+
|
|
24
|
+
export { useUnit };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadUnit,
|
|
3
|
+
saveUnit
|
|
4
|
+
} from "../chunk-YPOB3BBR.js";
|
|
5
|
+
|
|
6
|
+
// src/react/use-unit.ts
|
|
7
|
+
import { useEffect, useState } from "react";
|
|
8
|
+
var useUnit = (key) => {
|
|
9
|
+
const [unit, setUnit] = useState("millimeters");
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
setUnit(loadUnit(globalThis.localStorage ?? null, key));
|
|
12
|
+
}, [key]);
|
|
13
|
+
const choose = (next) => {
|
|
14
|
+
setUnit(next);
|
|
15
|
+
saveUnit(globalThis.localStorage ?? null, key, next);
|
|
16
|
+
};
|
|
17
|
+
return [unit, choose];
|
|
18
|
+
};
|
|
19
|
+
export {
|
|
20
|
+
useUnit
|
|
21
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@toolpath/app-support",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Reusable logic for a Toolpath application: preferences, contexts and route helpers",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=20"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/toolpath/ui-packages.git",
|
|
12
|
+
"directory": "packages/app-support"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://developers.toolpath.com",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/toolpath/ui-packages/issues"
|
|
17
|
+
},
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public",
|
|
20
|
+
"registry": "https://registry.npmjs.org"
|
|
21
|
+
},
|
|
22
|
+
"type": "module",
|
|
23
|
+
"main": "./dist/index.js",
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./react": {
|
|
31
|
+
"types": "./dist/react/index.d.ts",
|
|
32
|
+
"import": "./dist/react/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./package.json": "./package.json"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"LICENSE",
|
|
39
|
+
"README.md"
|
|
40
|
+
],
|
|
41
|
+
"sideEffects": false,
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsup src/index.ts src/react/index.ts --format esm --dts --clean --external react --external react-dom",
|
|
44
|
+
"check-types": "tsc --noEmit",
|
|
45
|
+
"test": "vitest run"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@toolpath/tool-support": "workspace:^"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"react": "^19.0.0",
|
|
52
|
+
"react-dom": "^19.0.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@testing-library/react": "^16.3.2",
|
|
56
|
+
"@types/node": "24.10.1",
|
|
57
|
+
"@types/react": "^19.0.0",
|
|
58
|
+
"@types/react-dom": "^19.0.0",
|
|
59
|
+
"jsdom": "^30.0.1",
|
|
60
|
+
"react": "19.2.0",
|
|
61
|
+
"react-dom": "19.2.0",
|
|
62
|
+
"tsup": "8.5.1",
|
|
63
|
+
"typescript": "5.9.3",
|
|
64
|
+
"vitest": "4.1.10"
|
|
65
|
+
}
|
|
66
|
+
}
|