@toolpath/tool-drawing 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 +117 -0
- package/dist/chunk-7ZID4QRO.js +34 -0
- package/dist/chunk-OUMNS4RI.js +225 -0
- package/dist/clearance/index.d.ts +205 -0
- package/dist/clearance/index.js +487 -0
- package/dist/geometry/index.d.ts +102 -0
- package/dist/geometry/index.js +6 -0
- package/dist/index.d.ts +353 -0
- package/dist/index.js +846 -0
- package/dist/sheet-D0LSO7qP.d.ts +183 -0
- package/package.json +67 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import { ViewerAssembly, Outline } from './geometry/index.js';
|
|
2
|
+
export { Provenance, ViewerHolder, ViewerTool } from './geometry/index.js';
|
|
3
|
+
import { F as Frame, S as Sheet, T as Theme, P as Padding } from './sheet-D0LSO7qP.js';
|
|
4
|
+
export { B as Box, E as Extent, a as FrameOptions, O as Orientation, b as SHEETS, f as frameFor, o as orientationFor, t as typeSizeFor } from './sheet-D0LSO7qP.js';
|
|
5
|
+
import * as react from 'react';
|
|
6
|
+
import { ReactNode } from 'react';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* What a drawing of this tool dimensions, and where each dimension goes.
|
|
10
|
+
*
|
|
11
|
+
* **Pure, and here rather than in the component**, because where a dimension
|
|
12
|
+
* line sits is arithmetic: which ones apply to this tool, what each one
|
|
13
|
+
* measures, and — the part a component would get wrong quietly — which lane
|
|
14
|
+
* each length runs in so that no two lines cross. The drawing turns these into
|
|
15
|
+
* SVG and nothing else.
|
|
16
|
+
*
|
|
17
|
+
* The space is the outline's own: millimetres, `z` above the tip, `r` from the
|
|
18
|
+
* axis. Every length is measured **from the tip**, which is where a machinist
|
|
19
|
+
* measures from and where every rule in the sheet measures from.
|
|
20
|
+
*
|
|
21
|
+
* Only stated numbers are dimensioned. A drawing that carries a figure the
|
|
22
|
+
* vendor never published is worse than one that carries fewer — the note under
|
|
23
|
+
* the drawing already names what was assumed, and a dimension line looks like a
|
|
24
|
+
* measurement whatever the note says.
|
|
25
|
+
*
|
|
26
|
+
* ## Sides are `minus` and `plus`, not `left` and `right`
|
|
27
|
+
*
|
|
28
|
+
* This model was written for a drawing that only ran vertically, where the two
|
|
29
|
+
* flanks of the tool were reliably the left and right of the screen. They are
|
|
30
|
+
* not any more: the frame lays a tool along whichever axis its panel is longer
|
|
31
|
+
* on, so the `-r` flank is the screen's left in one orientation and its top in
|
|
32
|
+
* the other. The names say which flank rather than where it lands, because the
|
|
33
|
+
* where is `toX`/`toY`'s alone.
|
|
34
|
+
*/
|
|
35
|
+
/** A length along the axis, drawn beside the stack. */
|
|
36
|
+
interface LengthDimension {
|
|
37
|
+
readonly code: string;
|
|
38
|
+
/** From the tip, in millimetres — always 0 for now, kept for a dimension that is not. */
|
|
39
|
+
readonly from: number;
|
|
40
|
+
readonly to: number;
|
|
41
|
+
/**
|
|
42
|
+
* Which line out from the stack this one runs in, 0 nearest.
|
|
43
|
+
*
|
|
44
|
+
* Shortest innermost, so the lines nest instead of crossing — the rule a
|
|
45
|
+
* drafting sheet follows and the reason this is worked out rather than
|
|
46
|
+
* listed in a fixed order.
|
|
47
|
+
*/
|
|
48
|
+
readonly lane: number;
|
|
49
|
+
}
|
|
50
|
+
/** A width across the axis, drawn at its own height. */
|
|
51
|
+
interface WidthDimension {
|
|
52
|
+
readonly code: string;
|
|
53
|
+
/** Half-width, in millimetres: the dimension runs from `-radius` to `+radius`. */
|
|
54
|
+
readonly radius: number;
|
|
55
|
+
/** Where up the tool it is measured, in millimetres above the tip. */
|
|
56
|
+
readonly at: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* An angle called out with a leader rather than measured between two lines.
|
|
60
|
+
*
|
|
61
|
+
* **A drill is its point** (Paul, 2026-09-01: "shouldn't a 2d rep of a drill be
|
|
62
|
+
* showing me a tip angle?"). On a ⌀1 drill the cone is three tenths of a
|
|
63
|
+
* millimetre tall — drawn to scale it is invisible, and the number is the only
|
|
64
|
+
* way the drawing says 140° rather than 118°.
|
|
65
|
+
*/
|
|
66
|
+
interface AngleDimension {
|
|
67
|
+
readonly code: string;
|
|
68
|
+
readonly degrees: number;
|
|
69
|
+
/** Where the leader points: a radius from the axis and a height above the tip. */
|
|
70
|
+
readonly at: {
|
|
71
|
+
readonly r: number;
|
|
72
|
+
readonly z: number;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
interface ToolDimensions {
|
|
76
|
+
readonly lengths: ReadonlyArray<LengthDimension>;
|
|
77
|
+
readonly widths: ReadonlyArray<WidthDimension>;
|
|
78
|
+
readonly angles: ReadonlyArray<AngleDimension>;
|
|
79
|
+
/** The corner radius, called out on the corner rather than dimensioned across it. */
|
|
80
|
+
readonly cornerRadius: number | null;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The dimensions for one assembly.
|
|
84
|
+
*
|
|
85
|
+
* With a holder, the tool's overall length is left off: most of the shank is
|
|
86
|
+
* inside the holder and a line to a face nobody can see reads as a mistake.
|
|
87
|
+
* What replaces it is the number the holder brings — how far the tool stands
|
|
88
|
+
* out of it.
|
|
89
|
+
*/
|
|
90
|
+
declare const dimensionsFor: (assembly: ViewerAssembly) => ToolDimensions;
|
|
91
|
+
declare const dimensionLabel: (code: string) => string;
|
|
92
|
+
/**
|
|
93
|
+
* How a length is written out.
|
|
94
|
+
*
|
|
95
|
+
* A function rather than a unit, because a unit system is the application's:
|
|
96
|
+
* this package has no opinion on whether a shop reads millimetres or inches,
|
|
97
|
+
* and owning one would mean owning its rounding too. Millimetres in, a string
|
|
98
|
+
* out; the default is only so the package draws something on its own.
|
|
99
|
+
*/
|
|
100
|
+
type FormatLength = (millimetres: number) => string;
|
|
101
|
+
declare const formatMillimetres: FormatLength;
|
|
102
|
+
/** One label's box on the drawing, before anything has been moved. */
|
|
103
|
+
interface LabelBox {
|
|
104
|
+
readonly key: string;
|
|
105
|
+
/** The inboard edge across the axis, and how far the box reaches outward. */
|
|
106
|
+
readonly across: number;
|
|
107
|
+
readonly width: number;
|
|
108
|
+
/** The end nearest the tip, and how far the box reaches along the axis. */
|
|
109
|
+
readonly along: number;
|
|
110
|
+
readonly height: number;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The same labels, moved apart until none covers another.
|
|
114
|
+
*
|
|
115
|
+
* **Because a dimension is only worth drawing if it can be read** (Paul,
|
|
116
|
+
* 2026-09-01). A tool 50 mm long with 4 mm of flute puts its flute length, its
|
|
117
|
+
* relief and its cutting diameter inside the bottom tenth of the drawing, and
|
|
118
|
+
* three figures land on each other however carefully each one is placed. Each
|
|
119
|
+
* label carries a box, so the boxes can be stacked: the one nearest the tip
|
|
120
|
+
* keeps its place, and anything that would cover it moves **away from the
|
|
121
|
+
* tip**, which is where the drawing has room.
|
|
122
|
+
*
|
|
123
|
+
* Pure arithmetic over rectangles — no measuring of text and no reading of the
|
|
124
|
+
* DOM, so it runs the same on a server as in a browser.
|
|
125
|
+
*
|
|
126
|
+
* **Along the axis, not up the screen.** The original moved a clash "up",
|
|
127
|
+
* which was the same direction only because the tool was always drawn
|
|
128
|
+
* standing. Away from the tip is what that meant, and it is what holds when
|
|
129
|
+
* the tool is laid on its side.
|
|
130
|
+
*/
|
|
131
|
+
declare const stackLabels: (boxes: ReadonlyArray<LabelBox>, gap?: number,
|
|
132
|
+
/**
|
|
133
|
+
* Boxes that cannot move: the drawing's own lines, so a figure rises clear
|
|
134
|
+
* of an extension line rather than sitting on it (Paul, 2026-09-01 — the
|
|
135
|
+
* figures moved in beside their own lanes, and the lines outboard of them
|
|
136
|
+
* cross those bands).
|
|
137
|
+
*/
|
|
138
|
+
fixed?: ReadonlyArray<LabelBox>) => Map<string, number>;
|
|
139
|
+
/**
|
|
140
|
+
* Where every figure on the drawing stands.
|
|
141
|
+
*
|
|
142
|
+
* **Each figure beside its own line, in the band just outboard of it** (Paul,
|
|
143
|
+
* 2026-09-01: "I'd love to put SFDM, LCF and shoulder dia closer to the part —
|
|
144
|
+
* like, inside the below holder and OAL lines"). One column in the far margin
|
|
145
|
+
* put the number for a dimension at the tool's edge as far from it as the
|
|
146
|
+
* number for the overall length, and the eye has to travel the width of the
|
|
147
|
+
* sheet to pair them up. So the margin is a series of bands: the widths sit in
|
|
148
|
+
* the first, just past their arrows, and each length's figure sits in the band
|
|
149
|
+
* outboard of its own lane.
|
|
150
|
+
*
|
|
151
|
+
* A band is only as wide as the widest figure in it, because the room it takes
|
|
152
|
+
* comes out of the tool.
|
|
153
|
+
*/
|
|
154
|
+
/** Which flank of the tool a figure stands off. */
|
|
155
|
+
type Side = 'minus' | 'plus';
|
|
156
|
+
/** The type a figure is set in, given the drawing's own size. */
|
|
157
|
+
declare const figureType: (fontSize: number) => number;
|
|
158
|
+
/** One figure, and the band it stands in. */
|
|
159
|
+
interface DimensionFigure {
|
|
160
|
+
readonly code: string;
|
|
161
|
+
readonly side: Side;
|
|
162
|
+
/** 0 is the band nearest the tool — the widths'; band `i + 1` is outboard of lane `i`. */
|
|
163
|
+
readonly band: number;
|
|
164
|
+
/** The lane this figure's dimension runs in on its own side, or null for a width. */
|
|
165
|
+
readonly lane: number | null;
|
|
166
|
+
readonly lines: ReadonlyArray<string>;
|
|
167
|
+
/** How far the figure reaches perpendicular to the tool axis. Bands are sized by this. */
|
|
168
|
+
readonly across: number;
|
|
169
|
+
/** How far it reaches parallel to the tool axis. The stacker moves figures along this. */
|
|
170
|
+
readonly along: number;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* How tall a block of this many lines is, set at that type size.
|
|
174
|
+
*
|
|
175
|
+
* The renderer sets type at {@link figureType} and leads it at 1.15, with half
|
|
176
|
+
* a line of padding above and below; this is that sum, and the two have to
|
|
177
|
+
* agree or a figure's box is not the size of the figure in it.
|
|
178
|
+
*/
|
|
179
|
+
declare const figureHeight: (lines: number, type: number) => number;
|
|
180
|
+
interface DimensionLayout {
|
|
181
|
+
readonly figures: ReadonlyArray<DimensionFigure>;
|
|
182
|
+
/** Per side, the width of every band, nearest the tool first. */
|
|
183
|
+
readonly bands: Readonly<Record<Side, ReadonlyArray<number>>>;
|
|
184
|
+
}
|
|
185
|
+
/** The room a side's bands take, measured out from the edge of the stack. */
|
|
186
|
+
interface BandRoom {
|
|
187
|
+
/** How far the width dimensions' arrows reach past the tool. */
|
|
188
|
+
readonly arrow: number;
|
|
189
|
+
/** The clearance between a band and the line beside it. */
|
|
190
|
+
readonly gap: number;
|
|
191
|
+
}
|
|
192
|
+
/** Where a band's inboard edge is: the offset a figure in it reads outward from. */
|
|
193
|
+
declare const bandOffset: (bands: ReadonlyArray<number>, band: number, room: BandRoom) => number;
|
|
194
|
+
/** Where a lane's line runs: just outboard of the band that carries its figure. */
|
|
195
|
+
declare const laneOffset: (bands: ReadonlyArray<number>, lane: number, room: BandRoom) => number;
|
|
196
|
+
/** Everything one side needs, out to the far edge of its last band. */
|
|
197
|
+
declare const bandRoom: (bands: ReadonlyArray<number>, room: BandRoom) => number;
|
|
198
|
+
/**
|
|
199
|
+
* Every figure, on the side and in the band it belongs to.
|
|
200
|
+
*
|
|
201
|
+
* The sides alternate — lengths by lane, widths by their own order — so
|
|
202
|
+
* neither margin runs away with the whole drawing while the other stands
|
|
203
|
+
* empty. Where the drawing has something beside it, everything stays on the
|
|
204
|
+
* one flank.
|
|
205
|
+
*/
|
|
206
|
+
declare const dimensionLayout: (model: ToolDimensions, format: FormatLength, fontSize: number, sides?: "one" | "both",
|
|
207
|
+
/**
|
|
208
|
+
* **Whether horizontal text runs parallel to the tool axis.**
|
|
209
|
+
*
|
|
210
|
+
* The one fact about the drawing's orientation that this model cannot do
|
|
211
|
+
* without, and it is here rather than in the renderer so that it is stated
|
|
212
|
+
* once, in a pure function, with a test on it.
|
|
213
|
+
*
|
|
214
|
+
* Everything else in this package is orientation-agnostic because a
|
|
215
|
+
* millimetre is a millimetre whichever way the axis runs. Type is the
|
|
216
|
+
* exception: **text does not rotate.** A figure two lines deep and twelve
|
|
217
|
+
* characters wide is wide on the screen either way, so when the tool is laid
|
|
218
|
+
* along the screen's width that figure reaches mostly *along* the tool, and
|
|
219
|
+
* when the tool stands up it reaches *across* it. The bands are sized on the
|
|
220
|
+
* across measure, so which of the two the type contributes decides how much
|
|
221
|
+
* room the margins take — and getting it backwards pads the wrong axis by a
|
|
222
|
+
* factor of about five.
|
|
223
|
+
*/
|
|
224
|
+
textAlongAxis?: boolean) => DimensionLayout;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* What `<ToolDrawing>` hands the things drawn inside it.
|
|
228
|
+
*
|
|
229
|
+
* **A child cannot work this out for itself, and should not try.** The panel is
|
|
230
|
+
* measured by a `ResizeObserver` on an `<svg>` the consumer never holds, and
|
|
231
|
+
* the chrome the dimension bands take is settled from that measurement — so a
|
|
232
|
+
* child that wanted to draw in the drawing's own coordinates had no way to
|
|
233
|
+
* learn them. The one consumer that needed them ended up re-deriving the frame
|
|
234
|
+
* from the same inputs and keeping a lockstep test to catch the drift, which is
|
|
235
|
+
* a workaround for a hole in this component's surface rather than a design.
|
|
236
|
+
*
|
|
237
|
+
* So the frame is published to the subtree instead. `frame` carries the scale,
|
|
238
|
+
* the viewBox and the two mapping functions; `outline` is what was drawn, for a
|
|
239
|
+
* child that needs the extent; `sheet` is the ink, so an overlay draws in the
|
|
240
|
+
* same palette without being told the theme twice.
|
|
241
|
+
*/
|
|
242
|
+
interface DrawingContext {
|
|
243
|
+
readonly frame: Frame;
|
|
244
|
+
readonly outline: Outline;
|
|
245
|
+
readonly sheet: Sheet;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* The frame the surrounding `<ToolDrawing>` settled on, or `null` outside one.
|
|
249
|
+
*
|
|
250
|
+
* Null rather than throwing, because a caller may legitimately pass the frame
|
|
251
|
+
* explicitly — a test framing a fixture, or a drawing composed by hand — and
|
|
252
|
+
* the props stay the override.
|
|
253
|
+
*/
|
|
254
|
+
declare const useDrawingContext: () => DrawingContext | null;
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* The assembly, drawn.
|
|
258
|
+
*
|
|
259
|
+
* A side elevation from stated dimensions, fitted to the stack so the assembly
|
|
260
|
+
* fills the panel. Nothing here measures or scales: {@link frameFor} settled
|
|
261
|
+
* all of that, and this places what it decided.
|
|
262
|
+
*
|
|
263
|
+
* **Outlined, not blocked in** (Paul, 2026-09-01, against the drawings in the
|
|
264
|
+
* geometry write-up): a drawing of a tool is a silhouette with its sections
|
|
265
|
+
* shaded lightly, so a dimension line that crosses it stays readable.
|
|
266
|
+
*
|
|
267
|
+
* **Every line is solid**: flutes pale yellow, shank one light grey whatever
|
|
268
|
+
* its provenance, the holder grey up to the spindle connection, which is
|
|
269
|
+
* darker. What was derived or assumed is on the element as `data-provenance`,
|
|
270
|
+
* and named in the note under the drawing.
|
|
271
|
+
*/
|
|
272
|
+
interface ToolDrawingProps {
|
|
273
|
+
readonly assembly: ViewerAssembly;
|
|
274
|
+
/**
|
|
275
|
+
* The sheet to draw on. A package cannot reach the application's theme hook,
|
|
276
|
+
* so the application passes its own; dark is the default because the sheet
|
|
277
|
+
* that needed stating was the dark one.
|
|
278
|
+
*/
|
|
279
|
+
readonly theme?: Theme;
|
|
280
|
+
/** The name over the drawing. Falls back to the tool's own label. */
|
|
281
|
+
readonly caption?: string;
|
|
282
|
+
/**
|
|
283
|
+
* Draw the dimensions: every stated length and width, on the tool.
|
|
284
|
+
*
|
|
285
|
+
* Off by default, because the drawing is also used small — on a card beside
|
|
286
|
+
* a list, where a dimension line is noise. The panel that has room turns it
|
|
287
|
+
* on (Paul, 2026-09-01).
|
|
288
|
+
*/
|
|
289
|
+
readonly dimensions?: boolean;
|
|
290
|
+
/**
|
|
291
|
+
* Which flanks the dimension lanes may use.
|
|
292
|
+
*
|
|
293
|
+
* **Both, wherever both are free** (Paul, 2026-09-01): four lengths stacked
|
|
294
|
+
* down one side push the tool into the other half of the panel and read as a
|
|
295
|
+
* ladder. Where the drawing has something beside it — a feature section —
|
|
296
|
+
* the far flank belongs to that and the lanes stay on one.
|
|
297
|
+
*/
|
|
298
|
+
readonly dimensionSides?: 'one' | 'both';
|
|
299
|
+
/**
|
|
300
|
+
* How a length is written out. Millimetres in, a string out.
|
|
301
|
+
*
|
|
302
|
+
* The application's, because the unit a shop reads in is the application's
|
|
303
|
+
* and owning one would mean owning its rounding too.
|
|
304
|
+
*/
|
|
305
|
+
readonly formatLength?: FormatLength;
|
|
306
|
+
/**
|
|
307
|
+
* Extra room for chrome around the drawing, in pixels, on top of whatever
|
|
308
|
+
* the dimension bands ask for.
|
|
309
|
+
*
|
|
310
|
+
* Per flank where the caller needs it asymmetrically — drawing a feature
|
|
311
|
+
* section beside the tool means reserving the `plus` flank for it, and the
|
|
312
|
+
* overlay draws in exactly the room reserved.
|
|
313
|
+
*/
|
|
314
|
+
readonly padding?: number | Partial<Padding>;
|
|
315
|
+
/**
|
|
316
|
+
* What the sweep found fouling the material, as data.
|
|
317
|
+
*
|
|
318
|
+
* The verdict itself is not this package's: whether an assembly clears is
|
|
319
|
+
* answered by the caller's own engine, for a dozen callers that draw
|
|
320
|
+
* nothing. This is that answer's picture — the sections it names are painted
|
|
321
|
+
* as struck rather than as metal.
|
|
322
|
+
*
|
|
323
|
+
* **Matched by height as well as by part**, because one part can emit
|
|
324
|
+
* several segments: a holder's stated body and the diameter carried up above
|
|
325
|
+
* it are both `body`, and only one of them may be in the material.
|
|
326
|
+
*/
|
|
327
|
+
readonly collisions?: ReadonlyArray<{
|
|
328
|
+
readonly part: string;
|
|
329
|
+
readonly height: number;
|
|
330
|
+
}>;
|
|
331
|
+
/**
|
|
332
|
+
* The clearance verdict, for the caption: whether it cleared, and a sentence
|
|
333
|
+
* saying by how much. `@toolpath/tool-drawing/clearance` writes the sentence.
|
|
334
|
+
*/
|
|
335
|
+
readonly verdict?: {
|
|
336
|
+
readonly clears: boolean;
|
|
337
|
+
readonly note?: string | null;
|
|
338
|
+
} | null;
|
|
339
|
+
/**
|
|
340
|
+
* Drawn inside the sheet, over the tool: the clearance overlay, or anything
|
|
341
|
+
* else the caller wants in the drawing's own coordinates.
|
|
342
|
+
*
|
|
343
|
+
* A child rather than a prop of its own, so this module never imports the
|
|
344
|
+
* overlay and a consumer that does not draw one never loads it. The frame,
|
|
345
|
+
* the outline and the sheet reach it through context — see
|
|
346
|
+
* `drawing-context.tsx` for why a child cannot work them out for itself.
|
|
347
|
+
*/
|
|
348
|
+
readonly children?: ReactNode;
|
|
349
|
+
readonly className?: string;
|
|
350
|
+
}
|
|
351
|
+
declare const ToolDrawing: ({ assembly, theme, caption, dimensions, dimensionSides, formatLength, padding, collisions, verdict, children, className, }: ToolDrawingProps) => react.JSX.Element;
|
|
352
|
+
|
|
353
|
+
export { type AngleDimension, type BandRoom, type DimensionFigure, type DimensionLayout, type DrawingContext, type FormatLength, Frame, type LabelBox, type LengthDimension, Padding, Sheet, type Side, Theme, type ToolDimensions, ToolDrawing, type ToolDrawingProps, ViewerAssembly, type WidthDimension, bandOffset, bandRoom, dimensionLabel, dimensionLayout, dimensionsFor, figureHeight, figureType, formatMillimetres, laneOffset, stackLabels, useDrawingContext };
|