dsh-figmark 1.1.1 → 1.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/lib/client.js +118 -31
- package/market/index.json +2 -2
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -1083,6 +1083,20 @@ window.__ModuleLoader__.load({
|
|
|
1083
1083
|
* every colour the palette offers.
|
|
1084
1084
|
*/
|
|
1085
1085
|
const PIN_NUMBER_COLOR = "#ffffff";
|
|
1086
|
+
/**
|
|
1087
|
+
* Font size of the number inside a pin, in figure pixels.
|
|
1088
|
+
*
|
|
1089
|
+
* Scaled by the mark's weight as well as the figure: the rail that makes a pin bigger
|
|
1090
|
+
* makes its head bigger, and a head that grows around a fixed-size numeral reads as a
|
|
1091
|
+
* circle with a speck in it. The number is the pin's whole payload, so it keeps the
|
|
1092
|
+
* same share of the head at every size.
|
|
1093
|
+
* @param mark - the point mark whose pin is being drawn.
|
|
1094
|
+
* @param unit - the figure's size multiple.
|
|
1095
|
+
* @returns the font size to draw the number at.
|
|
1096
|
+
*/
|
|
1097
|
+
function pinFontSizeOf(mark, unit = 1) {
|
|
1098
|
+
return 11 * (mark.weight ?? 1) * unit;
|
|
1099
|
+
}
|
|
1086
1100
|
/** Normalize two opposite corners into a top-left origin and positive extents. */
|
|
1087
1101
|
function bounds(first, second) {
|
|
1088
1102
|
return {
|
|
@@ -1867,7 +1881,7 @@ window.__ModuleLoader__.load({
|
|
|
1867
1881
|
x: centre[0],
|
|
1868
1882
|
y: centre[1],
|
|
1869
1883
|
fontFamily: PIN_FONT_FAMILY,
|
|
1870
|
-
fontSize:
|
|
1884
|
+
fontSize: pinFontSizeOf(mark, unit),
|
|
1871
1885
|
fontWeight: 700,
|
|
1872
1886
|
fill: PIN_NUMBER_COLOR,
|
|
1873
1887
|
textAnchor: "middle",
|
|
@@ -2631,7 +2645,7 @@ window.__ModuleLoader__.load({
|
|
|
2631
2645
|
const centre = mark.kind === "point" ? pinNumberCentre(mark, unit) : void 0;
|
|
2632
2646
|
if (pin !== void 0 && centre !== void 0) {
|
|
2633
2647
|
parts.push(`<path d="${pin}" fill="${mark.color}" stroke="#ffffff" stroke-width="${2 * unit}" stroke-linejoin="round"/>`);
|
|
2634
|
-
if (number !== void 0) parts.push(`<text x="${centre[0]}" y="${centre[1]}" font-family="${PIN_FONT_FAMILY}" font-size="${
|
|
2648
|
+
if (number !== void 0) parts.push(`<text x="${centre[0]}" y="${centre[1]}" font-family="${PIN_FONT_FAMILY}" font-size="${pinFontSizeOf(mark, unit)}" font-weight="700" fill="${PIN_NUMBER_COLOR}" text-anchor="middle" dominant-baseline="central">${number}</text>`);
|
|
2635
2649
|
}
|
|
2636
2650
|
return parts.join("");
|
|
2637
2651
|
}
|
|
@@ -3292,33 +3306,25 @@ window.__ModuleLoader__.load({
|
|
|
3292
3306
|
cursor:ns-resize;transition:width .16s ease,background .16s ease,box-shadow .16s ease}
|
|
3293
3307
|
.da-weight:hover,.da-weight:focus-within{width:30px;background:var(--dsw-alias-bg-layer-2,#fff);
|
|
3294
3308
|
box-shadow:0 5px 18px rgba(20,40,80,.16),0 0 0 0.5px var(--dsw-alias-border-l2,currentColor)}
|
|
3295
|
-
/* The
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
transition:opacity .16s ease}
|
|
3304
|
-
.da-weight:hover::before,.da-weight:focus-within::before{opacity:1}
|
|
3305
|
-
/* The part already chosen, drawn from the bottom up in the brand colour. */
|
|
3306
|
-
.da-weight-fill{position:absolute;left:50%;bottom:14px;width:11px;transform:translateX(-50%);
|
|
3307
|
-
opacity:0;pointer-events:none;transition:opacity .16s ease;
|
|
3308
|
-
background:var(--dsw-alias-brand-primary,#176df2);
|
|
3309
|
-
clip-path:polygon(calc(50% - 0.5px) 100%,calc(50% + 0.5px) 100%,
|
|
3310
|
-
calc(50% + 5.5px) 0,calc(50% - 5.5px) 0)}
|
|
3311
|
-
.da-weight:hover .da-weight-fill,.da-weight:focus-within .da-weight-fill{opacity:1}
|
|
3309
|
+
/* The track is an svg in the body: a hairline at the bottom that opens into a rounded
|
|
3310
|
+
shoulder at the top. It is not a clip-path polygon because a polygon has no rounded
|
|
3311
|
+
ends — the corners were what made the wedge read as a cut-out blade rather than a
|
|
3312
|
+
part of the panel. preserveAspectRatio="none" stretches one 12x100 shape over the
|
|
3313
|
+
rail's height, so the shoulders stay smooth at any length. */
|
|
3314
|
+
.da-weight-svg{position:absolute;left:50%;top:12px;bottom:12px;width:18px;
|
|
3315
|
+
transform:translateX(-50%);opacity:0;pointer-events:none;transition:opacity .16s ease}
|
|
3316
|
+
.da-weight:hover .da-weight-svg,.da-weight:focus-within .da-weight-svg{opacity:1}
|
|
3312
3317
|
/* The knob sits on the value: the only part that shows at rest, so the rail reads as
|
|
3313
3318
|
a slider waiting to be touched rather than a bare rule. */
|
|
3314
|
-
.da-weight-knob{position:absolute;left:50%;width:11px;height:11px;
|
|
3315
|
-
transform:translateX(-50%);pointer-events:none;
|
|
3319
|
+
.da-weight-knob{position:absolute;left:50%;width:var(--da-knob-size,11px);height:var(--da-knob-size,11px);
|
|
3320
|
+
border-radius:50%;transform:translateX(-50%);pointer-events:none;
|
|
3316
3321
|
background:var(--dsw-alias-bg-layer-2,#fff);
|
|
3317
|
-
box-shadow:0 1px 4px rgba(20,40,80,.
|
|
3322
|
+
box-shadow:0 1px 4px rgba(20,40,80,.28),0 0 0 1px var(--dsw-alias-border-l3,currentColor);
|
|
3318
3323
|
transition:width .16s ease,height .16s ease,background .16s ease}
|
|
3324
|
+
.da-weight:hover,.da-weight:focus-within{--da-knob-size:15px}
|
|
3319
3325
|
.da-weight:hover .da-weight-knob,.da-weight:focus-within .da-weight-knob{
|
|
3320
|
-
|
|
3321
|
-
box-shadow:0 2px 7px rgba(20,40,80,.
|
|
3326
|
+
background:var(--dsw-alias-brand-primary,#176df2);
|
|
3327
|
+
box-shadow:0 2px 7px rgba(20,40,80,.3)}
|
|
3322
3328
|
/* The browser's own range, rotated upright and made transparent. It spans the whole
|
|
3323
3329
|
rail so a press anywhere on it lands on the slider — including on the knob, which
|
|
3324
3330
|
is why the knob is pointer-transparent. */
|
|
@@ -3491,7 +3497,7 @@ window.__ModuleLoader__.load({
|
|
|
3491
3497
|
come from the mark it belongs to. It is a pill rather than a card — no head, no
|
|
3492
3498
|
border between the field and the panel — so writing about a mark costs one line
|
|
3493
3499
|
over the figure instead of a box that covers it. */
|
|
3494
|
-
.da-float-detail{width:300px;gap:0;padding:4px;border-radius:22px;
|
|
3500
|
+
.da-float-detail{width:300px;max-width:calc(100% - 16px);gap:0;padding:4px;border-radius:22px;
|
|
3495
3501
|
flex-direction:row;align-items:flex-end;
|
|
3496
3502
|
box-shadow:0 8px 26px rgba(20,40,80,.2),0 0 0 1px rgba(20,40,80,.04)}
|
|
3497
3503
|
.da-float .da-comment{flex:1 1 auto;min-width:0;box-sizing:border-box;border:0;background:transparent;
|
|
@@ -3814,6 +3820,27 @@ window.__ModuleLoader__.load({
|
|
|
3814
3820
|
"#2f9e44"
|
|
3815
3821
|
];
|
|
3816
3822
|
/** Tools in toolbar order. */
|
|
3823
|
+
/**
|
|
3824
|
+
* The rail's track, drawn on an 18x100 grid and stretched to whatever height it gets.
|
|
3825
|
+
*
|
|
3826
|
+
* A hairline at the bottom opening into a round shoulder at the top: the control's
|
|
3827
|
+
* subject is thickness, so the track itself says which way is heavier. Every edge is
|
|
3828
|
+
* curved — straight flanks make a paper dart, and a square cap makes a cut-off blade —
|
|
3829
|
+
* so the profile is eased and the top is closed with an arc a little wider than the
|
|
3830
|
+
* shoulders. Stretching it vertically (preserveAspectRatio="none") costs nothing
|
|
3831
|
+
* visually: the only vertical features are straight lines, and the horizontal ones are
|
|
3832
|
+
* what the gradient is for.
|
|
3833
|
+
*/
|
|
3834
|
+
const WEIGHT_TRACK = [
|
|
3835
|
+
"M 8.2 100",
|
|
3836
|
+
"C 8.2 78 7.9 58 6.4 38",
|
|
3837
|
+
"C 5.4 25 3.2 16 1.9 11",
|
|
3838
|
+
"A 7.1 7.1 0 0 1 16.1 11",
|
|
3839
|
+
"C 14.8 16 12.6 25 11.6 38",
|
|
3840
|
+
"C 10.1 58 9.8 78 9.8 100",
|
|
3841
|
+
"A 0.8 0.8 0 0 1 8.2 100",
|
|
3842
|
+
"Z"
|
|
3843
|
+
].join(" ");
|
|
3817
3844
|
const TOOLS = [
|
|
3818
3845
|
{
|
|
3819
3846
|
tool: "select",
|
|
@@ -4063,9 +4090,27 @@ window.__ModuleLoader__.load({
|
|
|
4063
4090
|
const isVector = mediaType === "image/svg+xml";
|
|
4064
4091
|
const t = (0, react.useCallback)((key) => resolveTranslate(props, key), [props.t, props.localeId]);
|
|
4065
4092
|
const sessionId = props.sessionId ?? parsedAddress?.sessionId;
|
|
4093
|
+
/**
|
|
4094
|
+
* A private prefix for the rail's gradient and clip ids.
|
|
4095
|
+
*
|
|
4096
|
+
* Two bodies can be mounted at once (a PDF lays out one per page), and an id is
|
|
4097
|
+
* document-wide: sharing one would make every rail's fill follow the first rail's
|
|
4098
|
+
* selection. Declared here, with the other hooks, because the ids are read far below
|
|
4099
|
+
* the early returns for a figure that failed to load.
|
|
4100
|
+
*/
|
|
4101
|
+
const trackId = `da-weight-${(0, react.useId)().replaceAll(":", "")}`;
|
|
4066
4102
|
const stageRef = (0, react.useRef)(null);
|
|
4067
4103
|
/** The box a double clicked mark's detail is written in. */
|
|
4068
4104
|
const detailRef = (0, react.useRef)(null);
|
|
4105
|
+
/**
|
|
4106
|
+
* The comment pill around that box.
|
|
4107
|
+
*
|
|
4108
|
+
* Measured rather than the textarea inside it: the field gives up width to the two
|
|
4109
|
+
* hand-off buttons as soon as there is something to send, so a placement computed
|
|
4110
|
+
* from the field's box would put the buttons past the edge of the panel — which is
|
|
4111
|
+
* exactly what a comment pill against the right edge used to do.
|
|
4112
|
+
*/
|
|
4113
|
+
const pillRef = (0, react.useRef)(null);
|
|
4069
4114
|
const barRef = (0, react.useRef)(null);
|
|
4070
4115
|
const figureHostRef = (0, react.useRef)(null);
|
|
4071
4116
|
const surfaceRef = (0, react.useRef)(null);
|
|
@@ -4653,7 +4698,7 @@ window.__ModuleLoader__.load({
|
|
|
4653
4698
|
}
|
|
4654
4699
|
const panel = root.getBoundingClientRect();
|
|
4655
4700
|
const measured = host.getBoundingClientRect();
|
|
4656
|
-
const pillSize = measuredSize(
|
|
4701
|
+
const pillSize = measuredSize(pillRef.current, {
|
|
4657
4702
|
width: 300,
|
|
4658
4703
|
height: 48
|
|
4659
4704
|
});
|
|
@@ -5231,6 +5276,13 @@ window.__ModuleLoader__.load({
|
|
|
5231
5276
|
*/
|
|
5232
5277
|
const shownWeight = selected === null ? WEIGHT_TOOLS.has(tool) ? weight : null : selected.weight ?? 1;
|
|
5233
5278
|
/**
|
|
5279
|
+
* How far up the rail that value sits, from 0 at the lightest to 1 at the heaviest.
|
|
5280
|
+
*
|
|
5281
|
+
* One number for the fill, the knob and the input: computed three times the three
|
|
5282
|
+
* could round differently and the knob would sit a pixel off the fill it belongs to.
|
|
5283
|
+
*/
|
|
5284
|
+
const weightFraction = shownWeight === null ? 0 : (shownWeight - WEIGHT_MIN) / (4 - WEIGHT_MIN);
|
|
5285
|
+
/**
|
|
5234
5286
|
* Change one attribute of the selected mark, or of the next stroke when nothing
|
|
5235
5287
|
* is selected.
|
|
5236
5288
|
*
|
|
@@ -5518,6 +5570,7 @@ window.__ModuleLoader__.load({
|
|
|
5518
5570
|
className: "da-float da-float-detail",
|
|
5519
5571
|
role: "group",
|
|
5520
5572
|
"aria-label": t("detail"),
|
|
5573
|
+
ref: pillRef,
|
|
5521
5574
|
style: {
|
|
5522
5575
|
left: detailAt.left,
|
|
5523
5576
|
top: detailAt.top
|
|
@@ -5572,15 +5625,49 @@ window.__ModuleLoader__.load({
|
|
|
5572
5625
|
chooseWeight(Number(event.target.value));
|
|
5573
5626
|
}
|
|
5574
5627
|
}),
|
|
5575
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
5576
|
-
className: "da-weight-
|
|
5577
|
-
"
|
|
5578
|
-
|
|
5628
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
5629
|
+
className: "da-weight-svg",
|
|
5630
|
+
viewBox: "0 0 18 100",
|
|
5631
|
+
preserveAspectRatio: "none",
|
|
5632
|
+
"aria-hidden": "true",
|
|
5633
|
+
children: [
|
|
5634
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("defs", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("linearGradient", {
|
|
5635
|
+
id: `${trackId}-shade`,
|
|
5636
|
+
x1: "0",
|
|
5637
|
+
y1: "1",
|
|
5638
|
+
x2: "0",
|
|
5639
|
+
y2: "0",
|
|
5640
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("stop", {
|
|
5641
|
+
offset: "0",
|
|
5642
|
+
stopColor: "rgba(20,40,80,.05)"
|
|
5643
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("stop", {
|
|
5644
|
+
offset: "1",
|
|
5645
|
+
stopColor: "rgba(20,40,80,.2)"
|
|
5646
|
+
})]
|
|
5647
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("clipPath", {
|
|
5648
|
+
id: `${trackId}-cut`,
|
|
5649
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
5650
|
+
x: "0",
|
|
5651
|
+
y: 100 - weightFraction * 100,
|
|
5652
|
+
width: "18",
|
|
5653
|
+
height: weightFraction * 100
|
|
5654
|
+
})
|
|
5655
|
+
})] }),
|
|
5656
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
5657
|
+
d: WEIGHT_TRACK,
|
|
5658
|
+
fill: `url(#${trackId}-shade)`
|
|
5659
|
+
}),
|
|
5660
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
5661
|
+
d: WEIGHT_TRACK,
|
|
5662
|
+
fill: "var(--dsw-alias-brand-primary,#176df2)",
|
|
5663
|
+
clipPath: `url(#${trackId}-cut)`
|
|
5664
|
+
})
|
|
5665
|
+
]
|
|
5579
5666
|
}),
|
|
5580
5667
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5581
5668
|
className: "da-weight-knob",
|
|
5582
5669
|
"aria-hidden": true,
|
|
5583
|
-
style: { bottom: `calc(${
|
|
5670
|
+
style: { bottom: `calc(12px + ${weightFraction} * (100% - 24px - var(--da-knob-size, 11px)))` }
|
|
5584
5671
|
})
|
|
5585
5672
|
]
|
|
5586
5673
|
}),
|
package/market/index.json
CHANGED