@toolpath/dfm 0.1.0 → 0.2.1
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 +122 -6
- package/dfm.css +3 -2
- package/dist/{reach-CfmYU_yQ.d.ts → feature-record-BUoFFjN6.d.ts} +89 -1
- package/dist/index.d.ts +254 -3
- package/dist/index.js +1246 -250
- package/dist/model/index.d.ts +62 -43
- package/dist/model/index.js +276 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,6 +9,12 @@ as one JSON file.
|
|
|
9
9
|
It also draws a feature's reach chart: the walls beside the feature, how high
|
|
10
10
|
they stand and how far out.
|
|
11
11
|
|
|
12
|
+
And it shows a feature as the Engine read it — the feature panel: the features
|
|
13
|
+
a clicked face could mean, the rules the chosen one breaks, what was measured
|
|
14
|
+
of it, its reach, and its datasheet as sent. Its pinch points, the widest tool
|
|
15
|
+
standing where the feature is tightest, are placed here and drawn by
|
|
16
|
+
`@toolpath/viewer`.
|
|
17
|
+
|
|
12
18
|
The rules and the checker that counts them ship too, with no React, under
|
|
13
19
|
`@toolpath/dfm/model`.
|
|
14
20
|
|
|
@@ -28,15 +34,16 @@ Add the styles after Tailwind and the `@toolpath/ui` theme:
|
|
|
28
34
|
|
|
29
35
|
## Exports
|
|
30
36
|
|
|
31
|
-
| Entry point | What it is
|
|
32
|
-
| ----------------------- |
|
|
33
|
-
| `@toolpath/dfm` | `RuleList`, `Swatch`, the list's keyboard helpers, `ReachChart`, `ReachDrawing`, their types |
|
|
34
|
-
| `@toolpath/dfm/model` | The rules, `checkPart`, the rule-set file — no React, no DOM
|
|
35
|
-
| `@toolpath/dfm/dfm.css` | Lets the app's Tailwind see the list's and chart's classes
|
|
37
|
+
| Entry point | What it is |
|
|
38
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
39
|
+
| `@toolpath/dfm` | `RuleList`, `Swatch`, the list's keyboard helpers, `ReachChart`, `ReachDrawing`, the feature panel (`FeaturePanel`, `FeatureDetails`, `CandidateList`, `ComparisonTable`, `storageFolds`), their types |
|
|
40
|
+
| `@toolpath/dfm/model` | The rules, `checkPart`, the rule-set file, the feature panel's rows, pinch points — no React, no DOM |
|
|
41
|
+
| `@toolpath/dfm/dfm.css` | Lets the app's Tailwind see the list's and chart's classes |
|
|
36
42
|
|
|
37
43
|
## The rules are an input
|
|
38
44
|
|
|
39
|
-
The package ships no default rules and stores nothing
|
|
45
|
+
The package ships no default rules and stores nothing — not the rules, nor
|
|
46
|
+
which of the feature panel's sections are open. The app keeps the rules
|
|
40
47
|
— in memory, `localStorage`, a server — and passes them in with the functions
|
|
41
48
|
that change them:
|
|
42
49
|
|
|
@@ -96,3 +103,112 @@ height; `ReachDrawing` says so in its note.
|
|
|
96
103
|
This is not the clearance overlay in `@toolpath/tool-drawing/clearance`: that
|
|
97
104
|
draws the walls beside a cutting tool, to show whether the tool fits. This
|
|
98
105
|
draws the walls alone.
|
|
106
|
+
|
|
107
|
+
## Feature panel
|
|
108
|
+
|
|
109
|
+
`FeaturePanel` is the card a click on the part opens: every feature the face
|
|
110
|
+
belongs to, then the details of the one being read. With several faces
|
|
111
|
+
shift-clicked, each face's candidates sit under a letter, above a table of
|
|
112
|
+
what each was read as. It fills what it is put in — where it sits, and
|
|
113
|
+
whether it can be dragged, is the app's — and the app decides what a click
|
|
114
|
+
means: which faces, which candidates in which order, which is read.
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
import { FeatureDetails, FeaturePanel, storageFolds } from '@toolpath/dfm'
|
|
118
|
+
import { brokenRules, featureMeasurements, featureProfile } from '@toolpath/dfm/model'
|
|
119
|
+
|
|
120
|
+
const folds = storageFolds(localStorage, 'toolpath.fold.')
|
|
121
|
+
|
|
122
|
+
export const Inspector = () => (
|
|
123
|
+
<FeaturePanel
|
|
124
|
+
faces={[{ region, rows, selected }]}
|
|
125
|
+
active={0}
|
|
126
|
+
onSelect={(tag) => setSelected(tag)}
|
|
127
|
+
onHover={setHovered}
|
|
128
|
+
onClose={close}
|
|
129
|
+
folds={folds}
|
|
130
|
+
>
|
|
131
|
+
<FeatureDetails
|
|
132
|
+
feature={feature}
|
|
133
|
+
units="mm"
|
|
134
|
+
directionColor={directionHex}
|
|
135
|
+
profile={featureProfile(sheets[key], feature.featureType)}
|
|
136
|
+
required={check.required.has(key)}
|
|
137
|
+
onFrame={() => frame(feature.tag)}
|
|
138
|
+
rules={brokenRules(check, feature.tag, 'mm')}
|
|
139
|
+
measurements={{
|
|
140
|
+
status: 'ready',
|
|
141
|
+
value: featureMeasurements({ features, feature, sheets, units: 'mm' }),
|
|
142
|
+
}}
|
|
143
|
+
record={{ status: 'ready', value: records[key] ?? null }}
|
|
144
|
+
PopOut={AppWindow}
|
|
145
|
+
folds={folds}
|
|
146
|
+
/>
|
|
147
|
+
</FeaturePanel>
|
|
148
|
+
)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The parts work alone too. An app with an inspect panel of its own puts
|
|
152
|
+
`CandidateList` and `FeatureDetails` in it and fills their slots with its own
|
|
153
|
+
controls — a folder in a row's `detail`, a Pin button in its `action`, Zoom to
|
|
154
|
+
in the details' `actions`, a folder badge in `status`.
|
|
155
|
+
|
|
156
|
+
- **Rules broken** are `BrokenRule` rows: a colour, the rule's text, the figure
|
|
157
|
+
that broke it, and optionally the limit and a note on hover. `brokenRules`
|
|
158
|
+
builds them from this package's check; an app with a checker of its own
|
|
159
|
+
builds them from its hits.
|
|
160
|
+
- **Measurements** are `featureMeasurements` rows, each with how it was worked
|
|
161
|
+
out behind an ⓘ. `inchMark` writes inches as `0.46"`.
|
|
162
|
+
- **Reach, the datasheet fields and the raw record** read the feature's
|
|
163
|
+
`FeatureRecord`: its report entry and datasheet as the API sent them.
|
|
164
|
+
- **Reads take time.** `measurements` and `record` are `Loadable`. While
|
|
165
|
+
`loading`, a section says what it is reading; on `error` it shows the app's
|
|
166
|
+
message and a Retry, held until `retryAt`.
|
|
167
|
+
- **The look** differs where apps want it to: `look.rules`, `look.selected` and
|
|
168
|
+
`look.muted`. Left out, it is the CAD viewer's.
|
|
169
|
+
- **Folds** are kept in the app's `FoldStore`; `storageFolds(storage, prefix)`
|
|
170
|
+
builds one over a `Storage`. Without one, a section remembers only while it
|
|
171
|
+
is mounted.
|
|
172
|
+
- **Pop-outs** need `PopOut`, the app's window component: the panel decides
|
|
173
|
+
what is open and fills it, and the app draws the frame. Define it at module
|
|
174
|
+
level, and render it through a portal to the page's body: the panel's blur
|
|
175
|
+
makes it the box a `fixed` window inside it would be placed in.
|
|
176
|
+
- **Keys:** Escape closes the panel and the arrow keys walk the candidates. On
|
|
177
|
+
a `CandidateList` used alone, put `candidateListKeys` on whatever holds it.
|
|
178
|
+
|
|
179
|
+
## Pinch points
|
|
180
|
+
|
|
181
|
+
The widest tool a feature admits, standing where the feature is tightest. The
|
|
182
|
+
data is here; the drawing is `@toolpath/viewer`'s `<ToolMarks>`, which knows
|
|
183
|
+
nothing of datasheets:
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
import { useMemo } from 'react'
|
|
187
|
+
import { pinchLabel, pinchMark, placePinchTool } from '@toolpath/dfm/model'
|
|
188
|
+
import { featureTriangles, ToolMarks, usePartContext } from '@toolpath/viewer'
|
|
189
|
+
|
|
190
|
+
// A child of <EnginePart> or <PartMesh>, which gives it the part.
|
|
191
|
+
export const PinchPoints = ({ datasheet, sheet, feature, units, shown }) => {
|
|
192
|
+
const { model, geometry } = usePartContext()
|
|
193
|
+
// Placing the tool searches the feature's faces: once per feature, not once per render.
|
|
194
|
+
const marks = useMemo(() => {
|
|
195
|
+
const mark = pinchMark(datasheet, sheet, feature.featureType)
|
|
196
|
+
const triangles = featureTriangles(model, geometry, feature.tag)
|
|
197
|
+
const tool = mark ? placePinchTool(mark, triangles, feature.machiningDirection) : null
|
|
198
|
+
return tool && mark ? [{ ...tool, ...pinchLabel(mark, units) }] : []
|
|
199
|
+
}, [datasheet, sheet, feature, model, geometry, units])
|
|
200
|
+
return <ToolMarks marks={marks} visible={shown} />
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
`placePinchTool` finds the datasheet's tool frame against the feature's faces —
|
|
205
|
+
the API gives its discs across the tool without saying which way x and y lie —
|
|
206
|
+
and stands the tool on the tightest disc, turned toward the wall that pinches
|
|
207
|
+
it. If the app moved the geometry to centre it, pass `origin`: where the CAD
|
|
208
|
+
file's zero now sits.
|
|
209
|
+
|
|
210
|
+
Show and hide it from the viewer's toolbar — `ViewerToolbar.ToolsButton` on a
|
|
211
|
+
`tools` control — with the state held by the app; start it shown. The tool is
|
|
212
|
+
an end mill made from its diameter and corner; to draw it as the app's other
|
|
213
|
+
tools are drawn, give the mark a `profile` from `@toolpath/tool-drawing`'s
|
|
214
|
+
outline of a flat or bull nose end mill that size.
|
package/dfm.css
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Lets the app's Tailwind see the classes the rule list
|
|
3
|
-
* Tailwind and `@toolpath/ui/theme.css`, whose colours
|
|
2
|
+
* Lets the app's Tailwind see the classes the rule list and the feature panel
|
|
3
|
+
* use. Import it after Tailwind and `@toolpath/ui/theme.css`, whose colours
|
|
4
|
+
* they are drawn in:
|
|
4
5
|
*
|
|
5
6
|
* @import 'tailwindcss';
|
|
6
7
|
* @import '@toolpath/ui/theme.css';
|
|
@@ -412,4 +412,92 @@ interface FeatureProfile {
|
|
|
412
412
|
}
|
|
413
413
|
declare const featureProfile: (sheet: FeatureSheet | undefined, featureType: string) => FeatureProfile;
|
|
414
414
|
|
|
415
|
-
|
|
415
|
+
/**
|
|
416
|
+
* A rule a feature breaks, as a row of its details says it: a coloured dot,
|
|
417
|
+
* the rule, and the figure that broke it. Neutral, so an app with rules of its
|
|
418
|
+
* own — the quoting app's, by severity — fills it from those, and an app on
|
|
419
|
+
* this package's checker fills it with {@link brokenRules}.
|
|
420
|
+
*/
|
|
421
|
+
interface BrokenRule {
|
|
422
|
+
/** Unique among one feature's rows: the rule's id. */
|
|
423
|
+
readonly key: string;
|
|
424
|
+
/** The dot: the rule's colour, or the app's colour for its severity. */
|
|
425
|
+
readonly color: string;
|
|
426
|
+
/** The rule: `Holes with L/D to top of part ≥ 8`, or a short label where `limit` says the rest. */
|
|
427
|
+
readonly text: string;
|
|
428
|
+
/** What the feature measured: `9.8`. Absent for a yes/no. */
|
|
429
|
+
readonly figure?: string;
|
|
430
|
+
/** The line it crossed, where `text` does not already say it: `≥ 8`. */
|
|
431
|
+
readonly limit?: string;
|
|
432
|
+
/** On hover: the rule written out, and why it matters. */
|
|
433
|
+
readonly note?: string;
|
|
434
|
+
}
|
|
435
|
+
/** The rules a feature breaks, as its details list them: one a measure, the worst, palette first. */
|
|
436
|
+
declare const brokenRules: (check: DfmCheck, tag: string, units: Units) => BrokenRule[];
|
|
437
|
+
/**
|
|
438
|
+
* The colour a feature is painted on the part: the one earliest in the
|
|
439
|
+
* palette of the rules it breaks, for a required feature. Read from a face
|
|
440
|
+
* painted alone (`region`), that face's colour where it is painted for this
|
|
441
|
+
* feature; a feature painted whole, its colour. Undefined otherwise.
|
|
442
|
+
*/
|
|
443
|
+
declare const featureColor: (check: DfmCheck, tag: string, region?: number | null) => string | undefined;
|
|
444
|
+
|
|
445
|
+
/** One row of a feature's details. */
|
|
446
|
+
interface Measurement {
|
|
447
|
+
/** Stable, so a list can key its rows. */
|
|
448
|
+
readonly key: string;
|
|
449
|
+
readonly label: string;
|
|
450
|
+
readonly value: string;
|
|
451
|
+
/** The same number in the other unit. Absent on a ratio or a count. */
|
|
452
|
+
readonly alt?: string;
|
|
453
|
+
/**
|
|
454
|
+
* How it was worked out from the datasheet, a line at a time: the fields it
|
|
455
|
+
* reads, by their path in the raw record, and the arithmetic, in the
|
|
456
|
+
* Engine's millimetres.
|
|
457
|
+
*/
|
|
458
|
+
readonly derivation: readonly string[];
|
|
459
|
+
/**
|
|
460
|
+
* A machining consideration rather than a measurement of the feature's own
|
|
461
|
+
* shape: the tool that cuts it, and how far it has to reach. The panel lists
|
|
462
|
+
* these under their own heading, for every kind of feature.
|
|
463
|
+
*/
|
|
464
|
+
readonly milling?: true;
|
|
465
|
+
/** A row that stands for a tool the viewer can draw on the part, by its kind. */
|
|
466
|
+
readonly tool?: SurfaceToolKind;
|
|
467
|
+
}
|
|
468
|
+
/** Which of a surface's finishing tools: a ball nose, or a bull nose with a flat between its corners. */
|
|
469
|
+
type SurfaceToolKind = 'ball' | 'bull';
|
|
470
|
+
/** Whether a feature type is read as a surface: see `SURFACE_TYPES`. */
|
|
471
|
+
declare const isSurfaceType: (featureType: string) => boolean;
|
|
472
|
+
/**
|
|
473
|
+
* The biggest ball nose a surface admits, mm: a ball's corner radius is half
|
|
474
|
+
* its diameter, so it is held under the tool fit's diameter and corner radius
|
|
475
|
+
* at once. None where the surface reports no fit, or admits no corner at all.
|
|
476
|
+
*/
|
|
477
|
+
declare const maxBallDiameter: (sheet: Pick<FeatureSheet, "fitToolDiameter" | "fitCornerRadius">) => number | undefined;
|
|
478
|
+
/**
|
|
479
|
+
* The rows a feature gets, in {@link ROW_ORDER}: its own geometry first, then
|
|
480
|
+
* where it sits in the part and the reach that makes, then the tools a
|
|
481
|
+
* surface admits. A row is left out rather than shown empty: "—" against a
|
|
482
|
+
* field this kind never reports reads as a measurement that failed.
|
|
483
|
+
*/
|
|
484
|
+
declare const featureMeasurements: ({ features, feature, sheets, units, inchMark, }: {
|
|
485
|
+
features: readonly DfmFeature[];
|
|
486
|
+
feature: DfmFeature;
|
|
487
|
+
sheets: FeatureSheets;
|
|
488
|
+
units: Units;
|
|
489
|
+
/** Writes inches as `0.46"` rather than `0.46 in`. */
|
|
490
|
+
inchMark?: boolean;
|
|
491
|
+
}) => Measurement[];
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Everything the API said about one feature: its entry in the part report and
|
|
495
|
+
* its datasheet, both as sent, so fields newer than any SDK are still there.
|
|
496
|
+
*/
|
|
497
|
+
interface FeatureRecord {
|
|
498
|
+
readonly feature: unknown;
|
|
499
|
+
/** Null where the API sent no datasheet for the feature. */
|
|
500
|
+
readonly datasheet: unknown;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
export { featureColor as A, type BrokenRule as B, CRITICAL_COLOR as C, type DfmRule as D, featureMeasurements as E, type FeatureSheets as F, featureProfile as G, featureSheet as H, featureTypeLabel as I, isNoReading as J, isSurfaceType as K, makeRule as L, type Measurement as M, maxBallDiameter as N, parseRules as O, PINCH_TOOL_MM as P, peakHeight as Q, type ReachCurve as R, type SurfaceToolKind as S, readPinch as T, type Units as U, readReachCurve as V, WARNING_COLOR as W, runStart as X, trimmedCurve as Y, withSurroundedFaces as Z, type DfmCheck as a, type DfmFeature as b, type FeatureProfile as c, type FeatureRecord as d, type DfmHit as e, type FeaturePinch as f, type FeatureSheet as g, type ClearanceFit as h, type DfmMetric as i, type DfmOp as j, type DfmQuantity as k, type DfmSources as l, type FactsKind as m, type FeatureAcross as n, type FeatureThreading as o, type PinchDisc as p, RULE_COLORS as q, type RangeHigh as r, type RangeLow as s, type ReportFeature as t, type RuleResult as u, brokenRules as v, checkPart as w, compareColors as x, describeRule as y, dfmFeatures as z };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { FC, KeyboardEvent, Ref } from 'react';
|
|
3
|
-
import { D as DfmRule, a as DfmCheck, b as DfmFeature, F as FeatureSheets, U as Units, R as ReachCurve, c as FeatureProfile } from './
|
|
2
|
+
import { FC, KeyboardEvent, Ref, ComponentType, ReactNode, ReactElement, HTMLAttributes } from 'react';
|
|
3
|
+
import { D as DfmRule, a as DfmCheck, b as DfmFeature, F as FeatureSheets, U as Units, R as ReachCurve, c as FeatureProfile, B as BrokenRule, M as Measurement, d as FeatureRecord } from './feature-record-BUoFFjN6.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* The rules the list shows, and how to change them. The app owns them —
|
|
@@ -114,4 +114,255 @@ declare const ReachChart: FC<ReachChartProps>;
|
|
|
114
114
|
/** A larger window's contents: the section, large, with what it is and how to read it. */
|
|
115
115
|
declare const ReachDrawing: FC<ReachChartProps>;
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Where the feature panel keeps which of its sections are open, so a section
|
|
119
|
+
* put away stays away from one feature to the next, and from one visit to the
|
|
120
|
+
* next. The app supplies it: the package stores nothing of its own.
|
|
121
|
+
*
|
|
122
|
+
* Sections are named by fixed ids — `rules`, `measurements`, `milling`,
|
|
123
|
+
* `reach`, `datasheet`, `raw`, `comparison`, `candidates`, and `candidates-A`,
|
|
124
|
+
* `candidates-B`… while comparing faces.
|
|
125
|
+
*/
|
|
126
|
+
interface FoldStore {
|
|
127
|
+
/** Whether a section was left open; undefined for one never folded, which then opens as it starts. */
|
|
128
|
+
read: (id: string) => boolean | undefined;
|
|
129
|
+
write: (id: string, open: boolean) => void;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* A fold store over a `Storage` — `localStorage`, `sessionStorage` — under a
|
|
133
|
+
* key prefix of the app's: `toolpath.fold.` keeps `toolpath.fold.reach` as
|
|
134
|
+
* `open` or `shut`. A storage that is missing, or that refuses (a private
|
|
135
|
+
* window, say), leaves the sections folding for as long as they are mounted.
|
|
136
|
+
*/
|
|
137
|
+
declare const storageFolds: (storage: Pick<Storage, "getItem" | "setItem"> | null | undefined, prefix: string) => FoldStore;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* How the feature panel looks where two apps want it to differ. Every field
|
|
141
|
+
* left out takes the first value, which is the CAD viewer's look.
|
|
142
|
+
*/
|
|
143
|
+
interface FeaturePanelLook {
|
|
144
|
+
/**
|
|
145
|
+
* A broken rule: `sentence` — the rule written out, the figure that broke it
|
|
146
|
+
* in grey; or `result` — a short label, the figure in the rule's colour, and
|
|
147
|
+
* the line it crossed, faded.
|
|
148
|
+
*/
|
|
149
|
+
rules?: 'sentence' | 'result';
|
|
150
|
+
/** The chosen candidate: `grey` and bold, or an `info` blue border and tint. */
|
|
151
|
+
selected?: 'grey' | 'info';
|
|
152
|
+
/** Secondary text: `pale` grey, or a `strong` grey that reads at full contrast. */
|
|
153
|
+
muted?: 'pale' | 'strong';
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** What the panel needs to name a feature: its tag, its type, and the way it is machined from. */
|
|
157
|
+
type FeatureIdentity = Pick<DfmFeature, 'tag' | 'featureType' | 'machiningDirection'>;
|
|
158
|
+
/**
|
|
159
|
+
* Something the app reads for the panel, and how far it has got: the panel
|
|
160
|
+
* says what it is waiting on, or what went wrong, in place of the section.
|
|
161
|
+
*/
|
|
162
|
+
type Loadable<T> = {
|
|
163
|
+
readonly status: 'loading';
|
|
164
|
+
} | {
|
|
165
|
+
readonly status: 'error';
|
|
166
|
+
/** In the app's own words: the API's answer, or that it asked to wait. */
|
|
167
|
+
readonly message: string;
|
|
168
|
+
/** Reads it again; left out, there is no Retry. */
|
|
169
|
+
readonly retry?: () => void;
|
|
170
|
+
/** No Retry before this, in `Date.now()` milliseconds: what a 429's `Retry-After` asks. */
|
|
171
|
+
readonly retryAt?: number;
|
|
172
|
+
} | {
|
|
173
|
+
readonly status: 'ready';
|
|
174
|
+
readonly value: T;
|
|
175
|
+
};
|
|
176
|
+
/** Which of a feature's sections pops out into a window of its own. */
|
|
177
|
+
type PopOutId = 'reach' | 'datasheet' | 'raw';
|
|
178
|
+
/**
|
|
179
|
+
* The app's window for a section popped out of the panel. The panel decides
|
|
180
|
+
* when one is open and what is in it; the app draws the frame — moved and
|
|
181
|
+
* sized as its page allows — and calls `onClose`. Define it once, at module
|
|
182
|
+
* level: one written inline remounts the window on every render. Render it
|
|
183
|
+
* through a portal to the page's body: the panel blurs what is behind it,
|
|
184
|
+
* which makes the panel the box a `fixed` window inside it is placed in.
|
|
185
|
+
*/
|
|
186
|
+
interface PopOutWindowProps {
|
|
187
|
+
id: PopOutId;
|
|
188
|
+
title: string;
|
|
189
|
+
/** Under the title: the feature it is of. */
|
|
190
|
+
subtitle: ReactNode;
|
|
191
|
+
icon: ReactElement;
|
|
192
|
+
/** In the header, before the close button: a copy button, say. */
|
|
193
|
+
action?: ReactNode;
|
|
194
|
+
onClose: () => void;
|
|
195
|
+
children: ReactNode;
|
|
196
|
+
}
|
|
197
|
+
type PopOutWindow = ComponentType<PopOutWindowProps>;
|
|
198
|
+
|
|
199
|
+
interface FeatureDetailsProps {
|
|
200
|
+
feature: FeatureIdentity;
|
|
201
|
+
/** Lengths in the reach chart; every other figure comes in written. */
|
|
202
|
+
units: Units;
|
|
203
|
+
/** The colour of the feature's machining direction, as the part shows it: any CSS colour. */
|
|
204
|
+
directionColor: string;
|
|
205
|
+
/** The feature beside its walls, for the reach chart: `featureProfile` of its sheet. */
|
|
206
|
+
profile: FeatureProfile;
|
|
207
|
+
/** In place of the feature's type: `Through hole ⌀ 6.35`. */
|
|
208
|
+
label?: ReactNode;
|
|
209
|
+
/** A feature the plan cannot do without: shows the REQUIRED pill. Left out, no pill. */
|
|
210
|
+
required?: boolean;
|
|
211
|
+
/** Turns the camera to the feature: shows a "Show this feature" button. */
|
|
212
|
+
onFrame?: () => void;
|
|
213
|
+
/** Right of the name: the app's own buttons. */
|
|
214
|
+
actions?: ReactNode;
|
|
215
|
+
/** At the end of the "Machined from" line: a folder badge, say. */
|
|
216
|
+
status?: ReactNode;
|
|
217
|
+
/** Under the title, before the sections: a sentence of the app's, its own action. */
|
|
218
|
+
children?: ReactNode;
|
|
219
|
+
/** The rules it breaks, as rows: see `brokenRules`. */
|
|
220
|
+
rules: readonly BrokenRule[];
|
|
221
|
+
/** Its measurements and milling considerations: `featureMeasurements`. */
|
|
222
|
+
measurements: Loadable<readonly Measurement[]>;
|
|
223
|
+
/** Its raw report entry and datasheet, for the reach chart. Null where the app has none. */
|
|
224
|
+
record: Loadable<FeatureRecord | null>;
|
|
225
|
+
/**
|
|
226
|
+
* The app's window, to pop the reach, the datasheet fields and the raw
|
|
227
|
+
* record out into, larger. Left out, there are no pop-out buttons.
|
|
228
|
+
*/
|
|
229
|
+
PopOut?: PopOutWindow;
|
|
230
|
+
look?: FeaturePanelLook;
|
|
231
|
+
folds?: FoldStore;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* One feature, as the Engine read it: its name and the way it is machined
|
|
235
|
+
* from, then the rules it breaks, what was measured of it, what that asks of
|
|
236
|
+
* the milling, and its reach.
|
|
237
|
+
*
|
|
238
|
+
* Then, shut until opened, every field of its datasheet and its raw API record,
|
|
239
|
+
* to read or copy.
|
|
240
|
+
*
|
|
241
|
+
* Each section folds away under its heading. A section waiting on something
|
|
242
|
+
* the app reads says so, and one whose read failed says why, with a Retry.
|
|
243
|
+
*/
|
|
244
|
+
declare const FeatureDetails: FC<FeatureDetailsProps>;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Up, down, Home and End through the candidates: put them on whatever holds
|
|
248
|
+
* the list — the whole panel, or just the list — as `ruleListKeys` is put on
|
|
249
|
+
* the rules. Each row is chosen as it is reached.
|
|
250
|
+
*/
|
|
251
|
+
declare const candidateListKeys: (event: react.KeyboardEvent<HTMLElement>) => void;
|
|
252
|
+
/** One feature a face could have meant, as its row says it. */
|
|
253
|
+
interface CandidateRow {
|
|
254
|
+
readonly feature: FeatureIdentity;
|
|
255
|
+
/** In place of the feature's type: `Blind hole ⌀ 6.35 × 4`. */
|
|
256
|
+
readonly label?: ReactNode;
|
|
257
|
+
/** The dot before it: the colour it is painted, or its direction's. Left out, a gap keeps the rows aligned. */
|
|
258
|
+
readonly color?: string;
|
|
259
|
+
/** How many rules it breaks: `2 rules`. */
|
|
260
|
+
readonly ruleCount?: number;
|
|
261
|
+
readonly required?: boolean;
|
|
262
|
+
/** Right-aligned in the row: the folder it is in, say. */
|
|
263
|
+
readonly detail?: ReactNode;
|
|
264
|
+
/** A second line under it: a note on how it overlaps another. */
|
|
265
|
+
readonly note?: ReactNode;
|
|
266
|
+
/** Beside the row, outside its button: the app's own action on it. */
|
|
267
|
+
readonly action?: ReactNode;
|
|
268
|
+
}
|
|
269
|
+
/** When comparing faces, which face this list is: its letter, and how to stop comparing it. */
|
|
270
|
+
interface ComparedFaceList {
|
|
271
|
+
readonly index: number;
|
|
272
|
+
/** The face being read: its letter is filled. */
|
|
273
|
+
readonly active: boolean;
|
|
274
|
+
readonly onStop?: () => void;
|
|
275
|
+
}
|
|
276
|
+
interface CandidateListProps {
|
|
277
|
+
/** In the app's order: the first is what a click meant first. */
|
|
278
|
+
rows: readonly CandidateRow[];
|
|
279
|
+
selected: string | null;
|
|
280
|
+
onSelect: (tag: string) => void;
|
|
281
|
+
/** A row under the pointer, and leaving it: left out, the rows preview nothing. */
|
|
282
|
+
onHover?: (tag: string | null) => void;
|
|
283
|
+
/** While comparing faces: this list's face. */
|
|
284
|
+
face?: ComparedFaceList;
|
|
285
|
+
look?: FeaturePanelLook;
|
|
286
|
+
folds?: FoldStore;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Every feature a clicked face belongs to, as rows to choose between: its
|
|
290
|
+
* colour, its name and the way it is machined from, how many rules it breaks,
|
|
291
|
+
* whether it is required, and whatever the app adds. The keys walk them, each
|
|
292
|
+
* chosen as it is reached; see {@link candidateListKeys}.
|
|
293
|
+
*/
|
|
294
|
+
declare const CandidateList: FC<CandidateListProps>;
|
|
295
|
+
|
|
296
|
+
/** One compared face: the feature it is read as, and what that feature is and measures. */
|
|
297
|
+
interface ComparedFace {
|
|
298
|
+
/** Null for a face no feature owns. */
|
|
299
|
+
readonly feature: FeatureIdentity | null;
|
|
300
|
+
/** Its machining direction's colour, as the part shows it. */
|
|
301
|
+
readonly directionColor: string;
|
|
302
|
+
/** Whether it is required. Left out on every face, the Required row goes. */
|
|
303
|
+
readonly required?: boolean;
|
|
304
|
+
readonly rules: readonly BrokenRule[];
|
|
305
|
+
readonly measurements: readonly Measurement[];
|
|
306
|
+
}
|
|
307
|
+
interface ComparisonTableProps {
|
|
308
|
+
faces: readonly ComparedFace[];
|
|
309
|
+
/** The face being read, whose column head is marked. */
|
|
310
|
+
active: number;
|
|
311
|
+
/** A column head chosen: that face's feature, to read. */
|
|
312
|
+
onSelect: (tag: string, face: number) => void;
|
|
313
|
+
onHover?: (tag: string | null) => void;
|
|
314
|
+
look?: FeaturePanelLook;
|
|
315
|
+
folds?: FoldStore;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* What each compared face was read as, side by side: a column per face, its
|
|
319
|
+
* feature at the head, and a row for each thing any of them has — its type,
|
|
320
|
+
* the way it is machined from, whether it is required, the rules it breaks,
|
|
321
|
+
* then every measurement. Rows where the readings disagree stand out; the rest
|
|
322
|
+
* are greyed.
|
|
323
|
+
*/
|
|
324
|
+
declare const ComparisonTable: FC<ComparisonTableProps>;
|
|
325
|
+
|
|
326
|
+
/** One face being inspected: the features it could mean, and the one being read. */
|
|
327
|
+
interface InspectedFace {
|
|
328
|
+
/** The face clicked; null for a feature chosen from a list, which has no candidates to show. */
|
|
329
|
+
readonly region: number | null;
|
|
330
|
+
/** In the app's order: see `CandidateList`. */
|
|
331
|
+
readonly rows: readonly CandidateRow[];
|
|
332
|
+
readonly selected: string | null;
|
|
333
|
+
}
|
|
334
|
+
interface FeaturePanelProps {
|
|
335
|
+
/** One face, or several while comparing. */
|
|
336
|
+
faces: readonly InspectedFace[];
|
|
337
|
+
/** Which face's feature the details are of. */
|
|
338
|
+
active: number;
|
|
339
|
+
/** A group of identical holes chosen together: how many, for the title. */
|
|
340
|
+
group?: number;
|
|
341
|
+
/** What each compared face was read as: the comparison table, while comparing. */
|
|
342
|
+
comparison?: readonly ComparedFace[];
|
|
343
|
+
onSelect: (tag: string, face: number) => void;
|
|
344
|
+
/** Takes a face out of the comparison. */
|
|
345
|
+
onDropFace?: (face: number) => void;
|
|
346
|
+
onHover?: (tag: string | null) => void;
|
|
347
|
+
onClose: () => void;
|
|
348
|
+
/** Spread on the header: an app's drag handle, say. */
|
|
349
|
+
headerProps?: HTMLAttributes<HTMLElement>;
|
|
350
|
+
className?: string;
|
|
351
|
+
look?: FeaturePanelLook;
|
|
352
|
+
folds?: FoldStore;
|
|
353
|
+
/** The active face's feature: its `<FeatureDetails>`. */
|
|
354
|
+
children?: ReactNode;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* The feature panel as a card: what a click on the part found — every feature
|
|
358
|
+
* the face belongs to, then the details of the one being read — or, with
|
|
359
|
+
* several faces shift-clicked, each face's candidates under a letter and a
|
|
360
|
+
* comparison of what each was read as.
|
|
361
|
+
*
|
|
362
|
+
* It fills what it is put in: where the card sits, and whether it moves, is
|
|
363
|
+
* the app's. Escape calls `onClose`, and the arrow keys walk the candidates
|
|
364
|
+
* from anywhere in it.
|
|
365
|
+
*/
|
|
366
|
+
declare const FeaturePanel: FC<FeaturePanelProps>;
|
|
367
|
+
|
|
368
|
+
export { CandidateList, type CandidateListProps, type CandidateRow, type ComparedFace, type ComparedFaceList, ComparisonTable, type ComparisonTableProps, type DfmRules, FeatureDetails, type FeatureDetailsProps, type FeatureIdentity, FeaturePanel, type FeaturePanelLook, type FeaturePanelProps, type FoldStore, type Hovered, type InspectedFace, type Loadable, type PopOutId, type PopOutWindow, type PopOutWindowProps, ReachChart, type ReachChartProps, ReachDrawing, RuleList, type RuleListProps, Swatch, type SwatchProps, candidateListKeys, isField, listKeys, ruleListKeys, storageFolds };
|