@stll/workspace-ui 0.9.1 → 0.10.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.
@@ -27,28 +27,5 @@ type FormatCalculationParams = {
27
27
  labels: CalculationLabels;
28
28
  };
29
29
  declare const formatCalculationResult: ({ result, formatters, labels }: FormatCalculationParams) => FormattedCalculation;
30
- /**
31
- * How many minor units make a major one, for this currency: 100 for CZK, 1 for
32
- * JPY, 1000 for KWD. It is a property of the currency and not of the reader, so
33
- * the lookup is deliberately locale-independent.
34
- *
35
- * A malformed code makes the `Intl.NumberFormat` constructor throw, before any
36
- * `?? 2` on its result could help, so the fallback has to wrap the call.
37
- */
38
- declare const currencyMinorUnitDigits: (currency: string) => number;
39
- type FormatMoneyCentsParams = {
40
- amountCents: number;
41
- currency: string;
42
- locale: string;
43
- };
44
- /**
45
- * Money is stored in minor units, and how many of them make a major one is a
46
- * property of the currency. Ask the currency rather than assuming a hundred.
47
- *
48
- * A code `Intl` rejects falls back to the amount beside the raw code: a column
49
- * showing "1500 A1C" is wrong-looking data, which is the truth, where a thrown
50
- * RangeError would take the whole board down with it.
51
- */
52
- declare const formatMoneyCents: ({ amountCents, currency, locale }: FormatMoneyCentsParams) => string;
53
30
  //#endregion
54
- export { CalculationFormatters, CalculationLabels, FormatCalculationParams, FormatMoneyCentsParams, FormattedCalculation, currencyMinorUnitDigits, formatCalculationResult, formatMoneyCents };
31
+ export { CalculationFormatters, CalculationLabels, FormatCalculationParams, FormattedCalculation, formatCalculationResult };
@@ -1,4 +1,4 @@
1
- import { Result } from "better-result";
1
+ import { panic } from "better-result";
2
2
  //#region src/calculation-format.ts
3
3
  /**
4
4
  * Turning a calculation result into the two strings a view shows: the compact
@@ -22,51 +22,13 @@ const formatCalculationResult = ({ result, formatters, labels }) => {
22
22
  };
23
23
  }
24
24
  case "unsupported": return line(labels.kind, labels.unavailable);
25
- default: return result;
25
+ default: return panic(`Unhandled result: ${String(result)}`);
26
26
  }
27
27
  };
28
- /**
29
- * Two, the ISO 4217 default, used when a stored code is one `Intl` will not
30
- * accept. Validation at the API boundary keeps those out, but a row written
31
- * before that constraint existed must still render rather than throw.
32
- */
33
- const DEFAULT_MINOR_UNIT_DIGITS = 2;
34
- /**
35
- * How many minor units make a major one, for this currency: 100 for CZK, 1 for
36
- * JPY, 1000 for KWD. It is a property of the currency and not of the reader, so
37
- * the lookup is deliberately locale-independent.
38
- *
39
- * A malformed code makes the `Intl.NumberFormat` constructor throw, before any
40
- * `?? 2` on its result could help, so the fallback has to wrap the call.
41
- */
42
- const currencyMinorUnitDigits = (currency) => {
43
- const resolved = Result.try(() => new Intl.NumberFormat("en", {
44
- style: "currency",
45
- currency
46
- }).resolvedOptions().maximumFractionDigits);
47
- if (resolved.isErr()) return DEFAULT_MINOR_UNIT_DIGITS;
48
- return resolved.value ?? DEFAULT_MINOR_UNIT_DIGITS;
49
- };
50
- /**
51
- * Money is stored in minor units, and how many of them make a major one is a
52
- * property of the currency. Ask the currency rather than assuming a hundred.
53
- *
54
- * A code `Intl` rejects falls back to the amount beside the raw code: a column
55
- * showing "1500 A1C" is wrong-looking data, which is the truth, where a thrown
56
- * RangeError would take the whole board down with it.
57
- */
58
- const formatMoneyCents = ({ amountCents, currency, locale }) => {
59
- const major = amountCents / 10 ** currencyMinorUnitDigits(currency);
60
- const formatted = Result.try(() => new Intl.NumberFormat(locale, {
61
- style: "currency",
62
- currency
63
- }).format(major));
64
- return formatted.isErr() ? `${major} ${currency}` : formatted.value;
65
- };
66
28
  const SEPARATOR = " · ";
67
29
  const line = (kind, value) => ({
68
30
  summary: `${kind} ${value}`,
69
31
  breakdown: []
70
32
  });
71
33
  //#endregion
72
- export { currencyMinorUnitDigits, formatCalculationResult, formatMoneyCents };
34
+ export { formatCalculationResult };
@@ -1,8 +1,9 @@
1
- import { formatCalculationResult, formatMoneyCents } from "./calculation-format.js";
1
+ import { formatCalculationResult } from "./calculation-format.js";
2
2
  import { applyCalculationSelection } from "./calculation-selection.js";
3
3
  import { CheckIcon, SigmaIcon } from "lucide-react";
4
4
  import { useFormatter, useLocale } from "use-intl";
5
5
  import { runCalculation } from "@stll/calculations";
6
+ import { formatMoneyCents } from "@stll/money";
6
7
  import { Button } from "@stll/ui/button";
7
8
  import { Menu, MenuItem, MenuPopup, MenuSub, MenuSubPopup, MenuSubTrigger, MenuTrigger } from "@stll/ui/menu";
8
9
  import { Tooltip, TooltipPopup, TooltipTrigger } from "@stll/ui/tooltip";
@@ -1,9 +1,9 @@
1
- import { formatMoneyCents } from "./calculation-format.js";
2
1
  import { emptyColor, resolveOptionColor } from "./colors.js";
3
2
  import { getClipFieldValueLabel } from "./field-value-logic.js";
4
3
  import { Result } from "better-result";
5
4
  import { Loader2Icon, SquareMinusIcon } from "lucide-react";
6
5
  import { useFormatter, useLocale, useTranslations } from "use-intl";
6
+ import { formatMoneyCents } from "@stll/money";
7
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
8
  import { BidiText } from "@stll/ui/bidi-text";
9
9
  import { Skeleton } from "@stll/ui/skeleton";
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { CalculationFormatters, CalculationLabels, FormatCalculationParams, FormatMoneyCentsParams, FormattedCalculation, currencyMinorUnitDigits, formatCalculationResult, formatMoneyCents } from "./calculation-format.js";
1
+ import { CalculationFormatters, CalculationLabels, FormatCalculationParams, FormattedCalculation, formatCalculationResult } from "./calculation-format.js";
2
2
  import { ApplyCalculationSelectionParams, CalculationSelection, applyCalculationSelection } from "./calculation-selection.js";
3
3
  import { CalculationKindPicker, CalculationKindPickerProps, CalculationPicker, CalculationPickerProps, CalculationProperty, CalculationResult, CalculationSummary, CalculationSummaryProps, ColumnCalculation, UseCalculationParams, WorkspaceCalculationLabels, useCalculation } from "./calculations.js";
4
4
  import { ColorVariants, OptionColor, emptyColor, optionColors, resolveOptionColor } from "./colors.js";
@@ -15,4 +15,4 @@ import { WorkspaceKanbanGroupingPicker } from "./kanban-grouping-picker.js";
15
15
  import { WorkspaceViewDirection, WorkspaceViewDropPosition, reorderWorkspaceViewIds, toWorkspaceViewDropPosition } from "./view-switcher.logic.js";
16
16
  import { WorkspaceViewSwitcher, WorkspaceViewSwitcherEditing, WorkspaceViewSwitcherItem, WorkspaceViewSwitcherProps, WorkspaceViewSwitcherReorder } from "./view-switcher.js";
17
17
  import { WorkspaceFrame, WorkspaceFrameEndRail, WorkspaceFrameInspector, WorkspaceFrameNavigation, WorkspaceFrameNavigationItem, WorkspaceFrameProps, WorkspaceFrameTopBar } from "./workspace-frame.js";
18
- export { type ApplyCalculationSelectionParams, CONDITION_OPERATORS, type CalculationFormatters, CalculationKindPicker, type CalculationKindPickerProps, type CalculationLabels, CalculationPicker, type CalculationPickerProps, type CalculationProperty, type CalculationResult, type CalculationSelection, CalculationSummary, type CalculationSummaryProps, type ColorVariants, ColumnCalculation, ConditionBuilder, type ConditionBuilderLabels, type ConditionCapabilities, type ConditionOperator, type CreateWorkspaceKanbanSchemaParams, FIELD_CONTENT_TYPES, type FieldContent, type FieldOption, type FieldOptionChoice, FieldValue, type FieldValueType, type FormatCalculationParams, type FormatMoneyCentsParams, type FormattedCalculation, type FormulaCellRenderCtx, type GenericProperty, IntFieldValue, KANBAN_EMPTY_GROUP_VISIBILITIES, KANBAN_SAVED_VIEW_STATE_VERSION, type KanbanBoardPresentation, type KanbanEmptyGroupVisibility, type KanbanPresentedBand, type KanbanPresentedLane, type KanbanSavedAxisState, type KanbanSavedGroupAxisState, type KanbanSavedGroupReference, type KanbanSavedSubgroupState, type KanbanSavedViewState, type KanbanSavedViewStateV1, MoneyFieldValue, type OptionColor, PersonFieldValue, PropertyIcon, type PropertyIconType, type ResolveWorkspaceKanbanViewParams, type ResolvedWorkspaceKanbanView, SortChips, type SortChipsLabels, type SortChipsProps, type SortDescriptor, type SortableProperty, TableSkeletonRows, type UseCalculationParams, type ValueEditorKind, type ValueEditorRenderCtx, type WorkspaceCalculationLabels, type WorkspaceFieldContent, WorkspaceFrame, type WorkspaceFrameEndRail, type WorkspaceFrameInspector, type WorkspaceFrameNavigation, type WorkspaceFrameNavigationItem, type WorkspaceFrameProps, type WorkspaceFrameTopBar, type WorkspaceKanbanBuiltInGroupLabel, type WorkspaceKanbanGroupingChoice, WorkspaceKanbanGroupingPicker, type WorkspaceKanbanGroupingPickerLabels, type WorkspaceKanbanGroupingPickerProps, type WorkspaceKanbanProperty, type WorkspaceViewDirection, type WorkspaceViewDropPosition, WorkspaceViewSwitcher, type WorkspaceViewSwitcherEditing, type WorkspaceViewSwitcherItem, type WorkspaceViewSwitcherProps, type WorkspaceViewSwitcherReorder, appendChild, applyCalculationSelection, asGroup, buildLeaf, createWorkspaceKanbanSchema, currencyMinorUnitDigits, emptyColor, fieldForNode, formatCalculationResult, formatMoneyCents, getClipFieldValueLabel, getWorkspaceKanbanGroupingChoices, isConditionOperator, isMultiValue, leafFromField, leafOperand, leafOperator, leafValueList, leafValueString, normalizeKanbanSavedViewState, operandsEqual, operatorsFor, optionColors, presentKanbanBoard, removeChild, reorderWorkspaceViewIds, replaceChild, resolveOptionColor, resolveWorkspaceKanbanView, sortDirectionHint, toWorkspaceViewDropPosition, useCalculation, valueEditorFor };
18
+ export { type ApplyCalculationSelectionParams, CONDITION_OPERATORS, type CalculationFormatters, CalculationKindPicker, type CalculationKindPickerProps, type CalculationLabels, CalculationPicker, type CalculationPickerProps, type CalculationProperty, type CalculationResult, type CalculationSelection, CalculationSummary, type CalculationSummaryProps, type ColorVariants, ColumnCalculation, ConditionBuilder, type ConditionBuilderLabels, type ConditionCapabilities, type ConditionOperator, type CreateWorkspaceKanbanSchemaParams, FIELD_CONTENT_TYPES, type FieldContent, type FieldOption, type FieldOptionChoice, FieldValue, type FieldValueType, type FormatCalculationParams, type FormattedCalculation, type FormulaCellRenderCtx, type GenericProperty, IntFieldValue, KANBAN_EMPTY_GROUP_VISIBILITIES, KANBAN_SAVED_VIEW_STATE_VERSION, type KanbanBoardPresentation, type KanbanEmptyGroupVisibility, type KanbanPresentedBand, type KanbanPresentedLane, type KanbanSavedAxisState, type KanbanSavedGroupAxisState, type KanbanSavedGroupReference, type KanbanSavedSubgroupState, type KanbanSavedViewState, type KanbanSavedViewStateV1, MoneyFieldValue, type OptionColor, PersonFieldValue, PropertyIcon, type PropertyIconType, type ResolveWorkspaceKanbanViewParams, type ResolvedWorkspaceKanbanView, SortChips, type SortChipsLabels, type SortChipsProps, type SortDescriptor, type SortableProperty, TableSkeletonRows, type UseCalculationParams, type ValueEditorKind, type ValueEditorRenderCtx, type WorkspaceCalculationLabels, type WorkspaceFieldContent, WorkspaceFrame, type WorkspaceFrameEndRail, type WorkspaceFrameInspector, type WorkspaceFrameNavigation, type WorkspaceFrameNavigationItem, type WorkspaceFrameProps, type WorkspaceFrameTopBar, type WorkspaceKanbanBuiltInGroupLabel, type WorkspaceKanbanGroupingChoice, WorkspaceKanbanGroupingPicker, type WorkspaceKanbanGroupingPickerLabels, type WorkspaceKanbanGroupingPickerProps, type WorkspaceKanbanProperty, type WorkspaceViewDirection, type WorkspaceViewDropPosition, WorkspaceViewSwitcher, type WorkspaceViewSwitcherEditing, type WorkspaceViewSwitcherItem, type WorkspaceViewSwitcherProps, type WorkspaceViewSwitcherReorder, appendChild, applyCalculationSelection, asGroup, buildLeaf, createWorkspaceKanbanSchema, emptyColor, fieldForNode, formatCalculationResult, getClipFieldValueLabel, getWorkspaceKanbanGroupingChoices, isConditionOperator, isMultiValue, leafFromField, leafOperand, leafOperator, leafValueList, leafValueString, normalizeKanbanSavedViewState, operandsEqual, operatorsFor, optionColors, presentKanbanBoard, removeChild, reorderWorkspaceViewIds, replaceChild, resolveOptionColor, resolveWorkspaceKanbanView, sortDirectionHint, toWorkspaceViewDropPosition, useCalculation, valueEditorFor };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { currencyMinorUnitDigits, formatCalculationResult, formatMoneyCents } from "./calculation-format.js";
1
+ import { formatCalculationResult } from "./calculation-format.js";
2
2
  import { applyCalculationSelection } from "./calculation-selection.js";
3
3
  import { CalculationKindPicker, CalculationPicker, CalculationSummary, ColumnCalculation, useCalculation } from "./calculations.js";
4
4
  import { emptyColor, optionColors, resolveOptionColor } from "./colors.js";
@@ -15,4 +15,4 @@ import { WorkspaceKanbanGroupingPicker } from "./kanban-grouping-picker.js";
15
15
  import { reorderWorkspaceViewIds, toWorkspaceViewDropPosition } from "./view-switcher.logic.js";
16
16
  import { WorkspaceViewSwitcher } from "./view-switcher.js";
17
17
  import { WorkspaceFrame } from "./workspace-frame.js";
18
- export { CONDITION_OPERATORS, CalculationKindPicker, CalculationPicker, CalculationSummary, ColumnCalculation, ConditionBuilder, FIELD_CONTENT_TYPES, FieldValue, IntFieldValue, KANBAN_EMPTY_GROUP_VISIBILITIES, KANBAN_SAVED_VIEW_STATE_VERSION, MoneyFieldValue, PersonFieldValue, PropertyIcon, SortChips, TableSkeletonRows, WorkspaceFrame, WorkspaceKanbanGroupingPicker, WorkspaceViewSwitcher, appendChild, applyCalculationSelection, asGroup, buildLeaf, createWorkspaceKanbanSchema, currencyMinorUnitDigits, emptyColor, fieldForNode, formatCalculationResult, formatMoneyCents, getClipFieldValueLabel, getWorkspaceKanbanGroupingChoices, isConditionOperator, isMultiValue, leafFromField, leafOperand, leafOperator, leafValueList, leafValueString, normalizeKanbanSavedViewState, operandsEqual, operatorsFor, optionColors, presentKanbanBoard, removeChild, reorderWorkspaceViewIds, replaceChild, resolveOptionColor, resolveWorkspaceKanbanView, sortDirectionHint, toWorkspaceViewDropPosition, useCalculation, valueEditorFor };
18
+ export { CONDITION_OPERATORS, CalculationKindPicker, CalculationPicker, CalculationSummary, ColumnCalculation, ConditionBuilder, FIELD_CONTENT_TYPES, FieldValue, IntFieldValue, KANBAN_EMPTY_GROUP_VISIBILITIES, KANBAN_SAVED_VIEW_STATE_VERSION, MoneyFieldValue, PersonFieldValue, PropertyIcon, SortChips, TableSkeletonRows, WorkspaceFrame, WorkspaceKanbanGroupingPicker, WorkspaceViewSwitcher, appendChild, applyCalculationSelection, asGroup, buildLeaf, createWorkspaceKanbanSchema, emptyColor, fieldForNode, formatCalculationResult, getClipFieldValueLabel, getWorkspaceKanbanGroupingChoices, isConditionOperator, isMultiValue, leafFromField, leafOperand, leafOperator, leafValueList, leafValueString, normalizeKanbanSavedViewState, operandsEqual, operatorsFor, optionColors, presentKanbanBoard, removeChild, reorderWorkspaceViewIds, replaceChild, resolveOptionColor, resolveWorkspaceKanbanView, sortDirectionHint, toWorkspaceViewDropPosition, useCalculation, valueEditorFor };
@@ -26,7 +26,7 @@ const normalizeKanbanSavedViewState = (state) => {
26
26
  version: 2
27
27
  };
28
28
  case 2: return state;
29
- default: return state;
29
+ default: return panic(`Unhandled state: ${String(state)}`);
30
30
  }
31
31
  };
32
32
  /**
@@ -21,6 +21,11 @@ const useLatestCallback = (callback) => {
21
21
  };
22
22
  const WorkspaceViewSwitcher = ({ activeViewId, ariaLabel, direction, reorder, views, addControl, editing, onViewChange, onViewContextMenu, onViewDoubleClick, renderActions, renderIcon }) => {
23
23
  const canReorder = reorder !== null;
24
+ const viewTabs = views.map((view) => ({
25
+ view,
26
+ actions: renderActions?.(view)
27
+ }));
28
+ const reserveActionSpace = viewTabs.some(({ actions }) => actions !== null && actions !== void 0 && typeof actions !== "boolean");
24
29
  const [instanceId] = useState(Symbol);
25
30
  const [stripContainer, setStripContainer] = useState(null);
26
31
  useEffect(() => {
@@ -47,25 +52,28 @@ const WorkspaceViewSwitcher = ({ activeViewId, ariaLabel, direction, reorder, vi
47
52
  className: cn("flex min-w-0 flex-1 items-center gap-1 px-2", TOOLBAR_ROW_HEIGHT),
48
53
  dir: direction,
49
54
  children: [/* @__PURE__ */ jsx("div", {
50
- className: "min-w-0 flex-1",
55
+ className: "h-full min-w-0 flex-1",
51
56
  ref: setStripContainer,
52
57
  children: /* @__PURE__ */ jsx(Tabs, {
58
+ className: "h-full gap-0",
53
59
  onValueChange: (value) => {
54
60
  if (typeof value === "string") onViewChange(value);
55
61
  },
56
62
  value: activeViewId,
57
63
  children: /* @__PURE__ */ jsx(TabsList, {
58
64
  "aria-label": ariaLabel,
65
+ className: "h-full data-[orientation=horizontal]:py-0",
59
66
  variant: "underline",
60
- children: views.map((view) => {
67
+ children: viewTabs.map(({ view, actions }) => {
61
68
  if (editing?.viewId === view.id) return /* @__PURE__ */ jsxs(TabsTab, {
69
+ className: cn("h-full sm:h-full", reserveActionSpace ? "pe-6.5" : void 0),
62
70
  nativeButton: false,
63
71
  render: /* @__PURE__ */ jsx("div", {}),
64
72
  value: view.id,
65
73
  children: [renderIcon(view), editing.renderLabel(view)]
66
74
  }, view.id);
67
75
  return /* @__PURE__ */ jsx(WorkspaceViewTab, {
68
- actions: renderActions?.(view),
76
+ actions,
69
77
  canReorder,
70
78
  direction,
71
79
  getDragData: reorder?.getDragData,
@@ -76,6 +84,7 @@ const WorkspaceViewSwitcher = ({ activeViewId, ariaLabel, direction, reorder, vi
76
84
  onDoubleClick: onViewDoubleClick,
77
85
  onReorder: handleReorder,
78
86
  renderIcon,
87
+ reserveActionSpace,
79
88
  view
80
89
  }, view.id);
81
90
  })
@@ -84,7 +93,7 @@ const WorkspaceViewSwitcher = ({ activeViewId, ariaLabel, direction, reorder, vi
84
93
  }), addControl]
85
94
  });
86
95
  };
87
- const WorkspaceViewTab = ({ actions, canReorder, direction, getDragData, getDropData, isDragBlocked, instanceId, onContextMenu, onDoubleClick, onReorder, renderIcon, view }) => {
96
+ const WorkspaceViewTab = ({ actions, canReorder, direction, getDragData, getDropData, isDragBlocked, instanceId, onContextMenu, onDoubleClick, onReorder, renderIcon, reserveActionSpace, view }) => {
88
97
  const [tabContainer, setTabContainer] = useState(null);
89
98
  const [dropPosition, setDropPosition] = useState(null);
90
99
  const canDrag = useLatestCallback(() => !isDragBlocked);
@@ -135,7 +144,7 @@ const WorkspaceViewTab = ({ actions, canReorder, direction, getDragData, getDrop
135
144
  view.id
136
145
  ]);
137
146
  return /* @__PURE__ */ jsxs("div", {
138
- className: "relative flex items-center",
147
+ className: "relative flex h-full items-center",
139
148
  ref: setTabContainer,
140
149
  children: [
141
150
  dropPosition !== null && /* @__PURE__ */ jsx("span", {
@@ -143,7 +152,7 @@ const WorkspaceViewTab = ({ actions, canReorder, direction, getDragData, getDrop
143
152
  className: cn("bg-primary pointer-events-none absolute inset-y-1 z-20 w-0.5 rounded-full", dropPosition === "before" ? "start-0" : "end-0")
144
153
  }),
145
154
  /* @__PURE__ */ jsxs(TabsTab, {
146
- className: actions === null || actions === void 0 ? void 0 : "pe-6.5",
155
+ className: cn("h-full sm:h-full", reserveActionSpace ? "pe-6.5" : void 0),
147
156
  onContextMenu: (event) => onContextMenu?.(view, event),
148
157
  onDoubleClick: (event) => onDoubleClick?.(view, event),
149
158
  value: view.id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stll/workspace-ui",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "description": "Reusable workspace presentation components and view helpers for Stella.",
5
5
  "keywords": [
6
6
  "calculations",
@@ -116,10 +116,10 @@
116
116
  "test:property": "bun test --preload @stll/property-testing/preload $(grep -rlF 'fc.assert' src --include='*.test.ts')"
117
117
  },
118
118
  "dependencies": {
119
- "@stll/calculations": "^0.1.0",
120
- "@stll/conditions": "^0.3.0",
121
- "@stll/money": "^0.1.0",
122
- "@stll/ui": "^0.25.0",
119
+ "@stll/calculations": "^0.1.1",
120
+ "@stll/conditions": "^0.3.1",
121
+ "@stll/money": "^0.2.0",
122
+ "@stll/ui": "^0.25.1",
123
123
  "better-result": "3.0.0",
124
124
  "lucide-react": "1.30.0",
125
125
  "use-intl": "4.13.5"
@@ -133,7 +133,7 @@
133
133
  "@tanstack/react-table": "9.2.4",
134
134
  "@types/react": "^19.2.17",
135
135
  "@types/react-dom": "^19.2.3",
136
- "bun-types": "1.4.1",
136
+ "bun-types": "1.4.2",
137
137
  "fast-check": "^4.9.0",
138
138
  "react": "^19.2.8",
139
139
  "react-dom": "^19.2.8",