@camstack/ui-library 1.2.336 → 1.2.338

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/CHANGELOG.md ADDED
@@ -0,0 +1,30 @@
1
+ # Changelog
2
+
3
+ All notable changes to this package are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [1.2.338] - 2026-10-27
11
+
12
+ ### Fixed
13
+
14
+ - The pet feeder panel shows the bowl amount and hides Mark refilled where the model cannot do it
15
+
16
+ ## [1.2.337] - 2026-10-27
17
+
18
+ ### Added
19
+
20
+ - The published package now includes its README and CHANGELOG.
21
+
22
+ ### Fixed
23
+
24
+ - The pet feeder panel no longer draws the desiccant readout
25
+
26
+ ## [1.2.336] - 2026-10-27
27
+
28
+ ### Added
29
+
30
+ - CamStack UI Library (@camstack/ui-library).
package/README.md ADDED
@@ -0,0 +1,19 @@
1
+ # CamStack UI Library
2
+
3
+ The shared React component library and Tailwind theme the CamStack admin UI, addon pages and widgets are built from.
4
+
5
+ <!-- readme:generated:start (derived from the manifest; edit outside this block) -->
6
+
7
+ Package `@camstack/ui-library` on npm.
8
+
9
+ ## Documentation
10
+
11
+ - [docs/architecture/ui.md](https://github.com/camstack/server/blob/main/docs/architecture/ui.md)
12
+ - [docs/ui/conventions.md](https://github.com/camstack/server/blob/main/docs/ui/conventions.md)
13
+ - [docs/ui/admin-patterns.md](https://github.com/camstack/server/blob/main/docs/ui/admin-patterns.md)
14
+ - [docs/ui/common-components.md](https://github.com/camstack/server/blob/main/docs/ui/common-components.md)
15
+ - [packages/ui-library/AGENTS.md](https://github.com/camstack/server/blob/main/packages/ui-library/AGENTS.md)
16
+
17
+ See [CHANGELOG.md](./CHANGELOG.md) for what changed in each version.
18
+
19
+ <!-- readme:generated:end -->
package/dist/index.cjs CHANGED
@@ -52600,17 +52600,18 @@ function ImageHeroCard({ trpc, deviceId, deviceName }) {
52600
52600
  /**
52601
52601
  * Pet-feeder controls for a `DeviceType.PetFeeder` device.
52602
52602
  *
52603
- * Reads the `pet-feeder` cap status slice (foodLevel / food1 / food2 /
52604
- * lowFood / batteryPower / desiccantLeftDays / feeding / status / error /
52603
+ * Reads the `pet-feeder` cap status slice (bowlFood / foodLevel / food1 / food2 /
52604
+ * lowFood / batteryPower / eating / feeding / status / error /
52605
52605
  * errorCode / isDualHopper + the four persisted settings) and renders:
52606
52606
  * - PetFeederInlineControl (device-list row): a compact food-level +
52607
52607
  * battery readout with a one-tap Feed button (default portion).
52608
52608
  * - PetFeederHeroCard (device-detail hero): the food-bowl fill gauge
52609
- * signature, battery + desiccant readouts, a manual-feed portion
52609
+ * signature, battery readout, a manual-feed portion
52610
52610
  * stepper honouring the 4-200 g hardware range (per-hopper on
52611
- * dual-hopper models), a maintenance action row (Call pet / Reset
52612
- * desiccant / Mark refilled) and the child-lock / indicator-light /
52613
- * feed-sound / volume settings.
52611
+ * dual-hopper models), a maintenance action row (Call pet /
52612
+ * Mark refilled) and the child-lock / indicator-light /
52613
+ * feed-sound / volume settings. The desiccant is a consumable: the
52614
+ * page's Consumables section draws it, never this card (D915).
52614
52615
  *
52615
52616
  * Mirrors the AC card's `useDeviceCapability` + inferred-cap pattern so
52616
52617
  * the row and hero never diverge. Actions are gated on `available`.
@@ -52622,16 +52623,6 @@ var VOLUME_MAX = 9;
52622
52623
  /** Amber kibble accent for the bowl fill; destructive red when low. */
52623
52624
  var KIBBLE = "#f59e0b";
52624
52625
  var KIBBLE_LOW = "#ef4444";
52625
- function desiccantLabel(t, seconds) {
52626
- const rendered = (0, _camstack_types.formatReading)({
52627
- value: seconds,
52628
- quantity: "duration"
52629
- });
52630
- return t("uiLibrary.petFeeder.desiccant", "{{text}}{{unit}} desiccant", {
52631
- text: rendered.text,
52632
- unit: rendered.unit
52633
- });
52634
- }
52635
52626
  function clampPortion(grams) {
52636
52627
  return Math.min(_camstack_types.PET_FEEDER_MANUAL_FEED_MAX, Math.max(_camstack_types.PET_FEEDER_MANUAL_FEED_MIN, grams));
52637
52628
  }
@@ -52677,17 +52668,10 @@ function PetFeederPanel({ trpc, deviceId, layout, optimistic }) {
52677
52668
  }),
52678
52669
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
52679
52670
  className: cn("inline-flex items-center gap-1 text-xs tabular-nums font-medium", display.lowFood ? "text-destructive" : "text-foreground"),
52680
- children: [
52681
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UtensilsCrossed, {
52682
- className: "h-3.5 w-3.5",
52683
- "aria-hidden": true
52684
- }),
52685
- display.foodLevel ?? "—",
52686
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
52687
- className: "text-foreground-subtle",
52688
- children: "g"
52689
- })
52690
- ]
52671
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(UtensilsCrossed, {
52672
+ className: "h-3.5 w-3.5",
52673
+ "aria-hidden": true
52674
+ }), display.bowlFood ?? "—"]
52691
52675
  }),
52692
52676
  display.batteryPower !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
52693
52677
  className: "inline-flex items-center gap-0.5 text-xs tabular-nums text-foreground-subtle",
@@ -52730,9 +52714,9 @@ function PetFeederPanel({ trpc, deviceId, layout, optimistic }) {
52730
52714
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52731
52715
  className: "flex items-center gap-4 rounded-lg border border-border/50 bg-surface-subtle/40 p-3",
52732
52716
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(BowlGauge, {
52733
- grams: display.foodLevel,
52717
+ grams: display.bowlFood,
52734
52718
  low: display.lowFood,
52735
- eating: display.feeding
52719
+ eating: display.eating
52736
52720
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52737
52721
  className: "flex min-w-0 flex-1 flex-col gap-1.5",
52738
52722
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -52740,10 +52724,10 @@ function PetFeederPanel({ trpc, deviceId, layout, optimistic }) {
52740
52724
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
52741
52725
  className: "text-3xl font-bold leading-none tabular-nums",
52742
52726
  style: { color: display.lowFood ? KIBBLE_LOW : KIBBLE },
52743
- children: display.foodLevel ?? "—"
52727
+ children: display.bowlFood ?? "—"
52744
52728
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
52745
52729
  className: "text-sm text-foreground-subtle",
52746
- children: t("uiLibrary.petFeeder.inBowl", "g in bowl")
52730
+ children: t("uiLibrary.petFeeder.inBowl", "in bowl")
52747
52731
  })]
52748
52732
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52749
52733
  className: "flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-foreground-subtle",
@@ -52752,10 +52736,6 @@ function PetFeederPanel({ trpc, deviceId, layout, optimistic }) {
52752
52736
  icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BatteryMedium, { className: "h-3.5 w-3.5" }),
52753
52737
  label: `${display.batteryPower}%`
52754
52738
  }),
52755
- display.desiccantLeftDays !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Readout, {
52756
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Wind, { className: "h-3.5 w-3.5" }),
52757
- label: desiccantLabel(t, display.desiccantLeftDays)
52758
- }),
52759
52739
  onBatteries && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
52760
52740
  className: "inline-flex items-center gap-1 font-medium text-amber-500",
52761
52741
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(BatteryWarning, {
@@ -52834,27 +52814,18 @@ function PetFeederPanel({ trpc, deviceId, layout, optimistic }) {
52834
52814
  onFeed: () => feedSingle(portion)
52835
52815
  }),
52836
52816
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
52837
- className: "grid grid-cols-3 gap-2",
52838
- children: [
52839
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActionButton, {
52840
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PawPrint, { className: "h-4 w-4" }),
52841
- label: t("uiLibrary.petFeeder.callPet", "Call pet"),
52842
- busy,
52843
- onClick: () => void cap.callPet({})
52844
- }),
52845
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActionButton, {
52846
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RefreshCw, { className: "h-4 w-4" }),
52847
- label: t("uiLibrary.petFeeder.resetDesiccant", "Reset desiccant"),
52848
- busy,
52849
- onClick: () => void cap.resetDesiccant({})
52850
- }),
52851
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActionButton, {
52852
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UtensilsCrossed, { className: "h-4 w-4" }),
52853
- label: t("uiLibrary.petFeeder.markRefilled", "Mark refilled"),
52854
- busy,
52855
- onClick: () => void cap.markFoodReplenished({})
52856
- })
52857
- ]
52817
+ className: "grid auto-cols-fr grid-flow-col gap-2",
52818
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActionButton, {
52819
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PawPrint, { className: "h-4 w-4" }),
52820
+ label: t("uiLibrary.petFeeder.callPet", "Call pet"),
52821
+ busy,
52822
+ onClick: () => void cap.callPet({})
52823
+ }), display.supportsMarkRefilled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActionButton, {
52824
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UtensilsCrossed, { className: "h-4 w-4" }),
52825
+ label: t("uiLibrary.petFeeder.markRefilled", "Mark refilled"),
52826
+ busy,
52827
+ onClick: () => void cap.markFoodReplenished({})
52828
+ })]
52858
52829
  }),
52859
52830
  display.feeding && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
52860
52831
  type: "button",
@@ -52967,7 +52938,7 @@ function Readout({ icon, label }) {
52967
52938
  }
52968
52939
  /**
52969
52940
  * Signature element — a food bowl whose kibble fills proportionally to the
52970
- * bowl reading (0–200 g). Amber when stocked, red when the low-food flag is
52941
+ * bowl reading (`bowlFood`). Amber when stocked, red when the low-food flag is
52971
52942
  * set; the kibble mound bobs while the pet is eating.
52972
52943
  */
52973
52944
  function BowlGauge({ grams, low, eating }) {
@@ -52980,7 +52951,7 @@ function BowlGauge({ grams, low, eating }) {
52980
52951
  height: 72,
52981
52952
  viewBox: "0 0 72 72",
52982
52953
  role: "img",
52983
- "aria-label": grams === null ? t("uiLibrary.petFeeder.levelUnknown", "Food level unknown") : t("uiLibrary.petFeeder.gramsInBowl", "{{grams}} grams in bowl", { grams }),
52954
+ "aria-label": grams === null ? t("uiLibrary.petFeeder.levelUnknown", "Food level unknown") : t("uiLibrary.petFeeder.gramsInBowl", "{{grams}} in bowl", { grams }),
52984
52955
  className: "shrink-0",
52985
52956
  children: [
52986
52957
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("clipPath", {
package/dist/index.js CHANGED
@@ -52576,17 +52576,18 @@ function ImageHeroCard({ trpc, deviceId, deviceName }) {
52576
52576
  /**
52577
52577
  * Pet-feeder controls for a `DeviceType.PetFeeder` device.
52578
52578
  *
52579
- * Reads the `pet-feeder` cap status slice (foodLevel / food1 / food2 /
52580
- * lowFood / batteryPower / desiccantLeftDays / feeding / status / error /
52579
+ * Reads the `pet-feeder` cap status slice (bowlFood / foodLevel / food1 / food2 /
52580
+ * lowFood / batteryPower / eating / feeding / status / error /
52581
52581
  * errorCode / isDualHopper + the four persisted settings) and renders:
52582
52582
  * - PetFeederInlineControl (device-list row): a compact food-level +
52583
52583
  * battery readout with a one-tap Feed button (default portion).
52584
52584
  * - PetFeederHeroCard (device-detail hero): the food-bowl fill gauge
52585
- * signature, battery + desiccant readouts, a manual-feed portion
52585
+ * signature, battery readout, a manual-feed portion
52586
52586
  * stepper honouring the 4-200 g hardware range (per-hopper on
52587
- * dual-hopper models), a maintenance action row (Call pet / Reset
52588
- * desiccant / Mark refilled) and the child-lock / indicator-light /
52589
- * feed-sound / volume settings.
52587
+ * dual-hopper models), a maintenance action row (Call pet /
52588
+ * Mark refilled) and the child-lock / indicator-light /
52589
+ * feed-sound / volume settings. The desiccant is a consumable: the
52590
+ * page's Consumables section draws it, never this card (D915).
52590
52591
  *
52591
52592
  * Mirrors the AC card's `useDeviceCapability` + inferred-cap pattern so
52592
52593
  * the row and hero never diverge. Actions are gated on `available`.
@@ -52598,16 +52599,6 @@ var VOLUME_MAX = 9;
52598
52599
  /** Amber kibble accent for the bowl fill; destructive red when low. */
52599
52600
  var KIBBLE = "#f59e0b";
52600
52601
  var KIBBLE_LOW = "#ef4444";
52601
- function desiccantLabel(t, seconds) {
52602
- const rendered = formatReading({
52603
- value: seconds,
52604
- quantity: "duration"
52605
- });
52606
- return t("uiLibrary.petFeeder.desiccant", "{{text}}{{unit}} desiccant", {
52607
- text: rendered.text,
52608
- unit: rendered.unit
52609
- });
52610
- }
52611
52602
  function clampPortion(grams) {
52612
52603
  return Math.min(PET_FEEDER_MANUAL_FEED_MAX, Math.max(PET_FEEDER_MANUAL_FEED_MIN, grams));
52613
52604
  }
@@ -52653,17 +52644,10 @@ function PetFeederPanel({ trpc, deviceId, layout, optimistic }) {
52653
52644
  }),
52654
52645
  /* @__PURE__ */ jsxs("span", {
52655
52646
  className: cn("inline-flex items-center gap-1 text-xs tabular-nums font-medium", display.lowFood ? "text-destructive" : "text-foreground"),
52656
- children: [
52657
- /* @__PURE__ */ jsx(UtensilsCrossed, {
52658
- className: "h-3.5 w-3.5",
52659
- "aria-hidden": true
52660
- }),
52661
- display.foodLevel ?? "—",
52662
- /* @__PURE__ */ jsx("span", {
52663
- className: "text-foreground-subtle",
52664
- children: "g"
52665
- })
52666
- ]
52647
+ children: [/* @__PURE__ */ jsx(UtensilsCrossed, {
52648
+ className: "h-3.5 w-3.5",
52649
+ "aria-hidden": true
52650
+ }), display.bowlFood ?? "—"]
52667
52651
  }),
52668
52652
  display.batteryPower !== null && /* @__PURE__ */ jsxs("span", {
52669
52653
  className: "inline-flex items-center gap-0.5 text-xs tabular-nums text-foreground-subtle",
@@ -52706,9 +52690,9 @@ function PetFeederPanel({ trpc, deviceId, layout, optimistic }) {
52706
52690
  /* @__PURE__ */ jsxs("div", {
52707
52691
  className: "flex items-center gap-4 rounded-lg border border-border/50 bg-surface-subtle/40 p-3",
52708
52692
  children: [/* @__PURE__ */ jsx(BowlGauge, {
52709
- grams: display.foodLevel,
52693
+ grams: display.bowlFood,
52710
52694
  low: display.lowFood,
52711
- eating: display.feeding
52695
+ eating: display.eating
52712
52696
  }), /* @__PURE__ */ jsxs("div", {
52713
52697
  className: "flex min-w-0 flex-1 flex-col gap-1.5",
52714
52698
  children: [/* @__PURE__ */ jsxs("div", {
@@ -52716,10 +52700,10 @@ function PetFeederPanel({ trpc, deviceId, layout, optimistic }) {
52716
52700
  children: [/* @__PURE__ */ jsx("span", {
52717
52701
  className: "text-3xl font-bold leading-none tabular-nums",
52718
52702
  style: { color: display.lowFood ? KIBBLE_LOW : KIBBLE },
52719
- children: display.foodLevel ?? "—"
52703
+ children: display.bowlFood ?? "—"
52720
52704
  }), /* @__PURE__ */ jsx("span", {
52721
52705
  className: "text-sm text-foreground-subtle",
52722
- children: t("uiLibrary.petFeeder.inBowl", "g in bowl")
52706
+ children: t("uiLibrary.petFeeder.inBowl", "in bowl")
52723
52707
  })]
52724
52708
  }), /* @__PURE__ */ jsxs("div", {
52725
52709
  className: "flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-foreground-subtle",
@@ -52728,10 +52712,6 @@ function PetFeederPanel({ trpc, deviceId, layout, optimistic }) {
52728
52712
  icon: /* @__PURE__ */ jsx(BatteryMedium, { className: "h-3.5 w-3.5" }),
52729
52713
  label: `${display.batteryPower}%`
52730
52714
  }),
52731
- display.desiccantLeftDays !== null && /* @__PURE__ */ jsx(Readout, {
52732
- icon: /* @__PURE__ */ jsx(Wind, { className: "h-3.5 w-3.5" }),
52733
- label: desiccantLabel(t, display.desiccantLeftDays)
52734
- }),
52735
52715
  onBatteries && /* @__PURE__ */ jsxs("span", {
52736
52716
  className: "inline-flex items-center gap-1 font-medium text-amber-500",
52737
52717
  children: [/* @__PURE__ */ jsx(BatteryWarning, {
@@ -52810,27 +52790,18 @@ function PetFeederPanel({ trpc, deviceId, layout, optimistic }) {
52810
52790
  onFeed: () => feedSingle(portion)
52811
52791
  }),
52812
52792
  /* @__PURE__ */ jsxs("div", {
52813
- className: "grid grid-cols-3 gap-2",
52814
- children: [
52815
- /* @__PURE__ */ jsx(ActionButton, {
52816
- icon: /* @__PURE__ */ jsx(PawPrint, { className: "h-4 w-4" }),
52817
- label: t("uiLibrary.petFeeder.callPet", "Call pet"),
52818
- busy,
52819
- onClick: () => void cap.callPet({})
52820
- }),
52821
- /* @__PURE__ */ jsx(ActionButton, {
52822
- icon: /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" }),
52823
- label: t("uiLibrary.petFeeder.resetDesiccant", "Reset desiccant"),
52824
- busy,
52825
- onClick: () => void cap.resetDesiccant({})
52826
- }),
52827
- /* @__PURE__ */ jsx(ActionButton, {
52828
- icon: /* @__PURE__ */ jsx(UtensilsCrossed, { className: "h-4 w-4" }),
52829
- label: t("uiLibrary.petFeeder.markRefilled", "Mark refilled"),
52830
- busy,
52831
- onClick: () => void cap.markFoodReplenished({})
52832
- })
52833
- ]
52793
+ className: "grid auto-cols-fr grid-flow-col gap-2",
52794
+ children: [/* @__PURE__ */ jsx(ActionButton, {
52795
+ icon: /* @__PURE__ */ jsx(PawPrint, { className: "h-4 w-4" }),
52796
+ label: t("uiLibrary.petFeeder.callPet", "Call pet"),
52797
+ busy,
52798
+ onClick: () => void cap.callPet({})
52799
+ }), display.supportsMarkRefilled && /* @__PURE__ */ jsx(ActionButton, {
52800
+ icon: /* @__PURE__ */ jsx(UtensilsCrossed, { className: "h-4 w-4" }),
52801
+ label: t("uiLibrary.petFeeder.markRefilled", "Mark refilled"),
52802
+ busy,
52803
+ onClick: () => void cap.markFoodReplenished({})
52804
+ })]
52834
52805
  }),
52835
52806
  display.feeding && /* @__PURE__ */ jsxs("button", {
52836
52807
  type: "button",
@@ -52943,7 +52914,7 @@ function Readout({ icon, label }) {
52943
52914
  }
52944
52915
  /**
52945
52916
  * Signature element — a food bowl whose kibble fills proportionally to the
52946
- * bowl reading (0–200 g). Amber when stocked, red when the low-food flag is
52917
+ * bowl reading (`bowlFood`). Amber when stocked, red when the low-food flag is
52947
52918
  * set; the kibble mound bobs while the pet is eating.
52948
52919
  */
52949
52920
  function BowlGauge({ grams, low, eating }) {
@@ -52956,7 +52927,7 @@ function BowlGauge({ grams, low, eating }) {
52956
52927
  height: 72,
52957
52928
  viewBox: "0 0 72 72",
52958
52929
  role: "img",
52959
- "aria-label": grams === null ? t("uiLibrary.petFeeder.levelUnknown", "Food level unknown") : t("uiLibrary.petFeeder.gramsInBowl", "{{grams}} grams in bowl", { grams }),
52930
+ "aria-label": grams === null ? t("uiLibrary.petFeeder.levelUnknown", "Food level unknown") : t("uiLibrary.petFeeder.gramsInBowl", "{{grams}} in bowl", { grams }),
52960
52931
  className: "shrink-0",
52961
52932
  children: [
52962
52933
  /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("clipPath", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/ui-library",
3
- "version": "1.2.336",
3
+ "version": "1.2.338",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/camstack/server.git",
@@ -40,7 +40,9 @@
40
40
  "files": [
41
41
  "dist",
42
42
  "src/tailwind",
43
- "assets"
43
+ "assets",
44
+ "README.md",
45
+ "CHANGELOG.md"
44
46
  ],
45
47
  "scripts": {
46
48
  "build": "vite build && npx tsx ../../scripts/emit-isolated-dts.ts --root . --src src --out dist",