react-led-digit 0.0.7 → 0.0.9

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.
@@ -1,25 +1,28 @@
1
+ /**
2
+ * Switches intrnal state periodically (visible), calling subscribers each time.
3
+ */
1
4
  type BlinkerSubscriber = (state: BlinkerState['visible']) => void;
2
5
  type BlinkerState = {
3
6
  timeout: null | ReturnType<typeof setTimeout>;
4
7
  subscribers: BlinkerSubscriber[];
5
- period: number;
6
8
  ratio: number;
9
+ period: number;
7
10
  visible: boolean;
8
- blinks: number;
9
11
  };
10
12
  type BlinkerOptions = {
11
13
  autoRun?: boolean;
12
- period?: BlinkerState['period'];
13
14
  ratio?: BlinkerState['ratio'];
15
+ period?: BlinkerState['period'];
14
16
  visible?: BlinkerState['visible'];
17
+ singleton?: boolean;
15
18
  };
16
19
  export declare class Blinker {
17
20
  #private;
18
21
  private static instance;
19
22
  constructor(options?: BlinkerOptions);
20
- get period(): BlinkerState['period'];
21
- get ratio(): BlinkerState['ratio'];
22
- get visible(): BlinkerState['visible'];
23
+ get period(): BlinkerState["period"];
24
+ get ratio(): BlinkerState["ratio"];
25
+ get visible(): BlinkerState["visible"];
23
26
  set period(val: BlinkerState['period']);
24
27
  set ratio(val: BlinkerState['ratio']);
25
28
  set visible(val: BlinkerState['visible']);
@@ -1,16 +1,19 @@
1
1
  "use strict";
2
+ /**
3
+ * Switches intrnal state periodically (visible), calling subscribers each time.
4
+ */
5
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
6
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
7
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
8
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
9
+ };
2
10
  var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
11
  if (kind === "m") throw new TypeError("Private method is not writable");
4
12
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
13
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
14
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
15
  };
8
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
- };
13
- var _Blinker_instances, _Blinker_initOptions, _Blinker_state, _Blinker_on, _Blinker_off;
16
+ var _Blinker_instances, _Blinker_options, _Blinker_state, _Blinker_on, _Blinker_off;
14
17
  Object.defineProperty(exports, "__esModule", { value: true });
15
18
  exports.Blinker = void 0;
16
19
  const defaultOptions = {
@@ -18,27 +21,34 @@ const defaultOptions = {
18
21
  period: 1000,
19
22
  ratio: 1,
20
23
  visible: true,
24
+ singleton: true,
21
25
  };
22
26
  class Blinker {
23
27
  constructor(options = defaultOptions) {
24
28
  _Blinker_instances.add(this);
25
- _Blinker_initOptions.set(this, defaultOptions); // store options
29
+ _Blinker_options.set(this, defaultOptions); // initial options
26
30
  _Blinker_state.set(this, {
27
- timeout: null,
28
- subscribers: [],
29
- period: defaultOptions.period,
30
31
  ratio: defaultOptions.ratio,
32
+ period: defaultOptions.period,
33
+ subscribers: [],
34
+ timeout: null,
31
35
  visible: defaultOptions.visible,
32
- blinks: 0,
33
36
  });
37
+ const init = () => {
38
+ __classPrivateFieldSet(this, _Blinker_options, Object.assign(Object.assign({}, __classPrivateFieldGet(this, _Blinker_options, "f")), options), "f"); // merge options
39
+ __classPrivateFieldGet(this, _Blinker_state, "f").period = __classPrivateFieldGet(this, _Blinker_options, "f").period;
40
+ __classPrivateFieldGet(this, _Blinker_state, "f").ratio = __classPrivateFieldGet(this, _Blinker_options, "f").ratio;
41
+ __classPrivateFieldGet(this, _Blinker_state, "f").visible = __classPrivateFieldGet(this, _Blinker_options, "f").visible;
42
+ if (__classPrivateFieldGet(this, _Blinker_options, "f").autoRun)
43
+ this.start();
44
+ };
45
+ if (options.singleton === false) {
46
+ init();
47
+ return this;
48
+ }
34
49
  if (!Blinker.instance) {
35
50
  Blinker.instance = this;
36
- __classPrivateFieldSet(this, _Blinker_initOptions, Object.assign(Object.assign({}, defaultOptions), options), "f");
37
- __classPrivateFieldGet(this, _Blinker_state, "f").period = __classPrivateFieldGet(this, _Blinker_initOptions, "f").period;
38
- __classPrivateFieldGet(this, _Blinker_state, "f").ratio = __classPrivateFieldGet(this, _Blinker_initOptions, "f").ratio;
39
- __classPrivateFieldGet(this, _Blinker_state, "f").visible = __classPrivateFieldGet(this, _Blinker_initOptions, "f").visible;
40
- if (__classPrivateFieldGet(this, _Blinker_initOptions, "f").autoRun)
41
- this.start();
51
+ init();
42
52
  }
43
53
  return Blinker.instance;
44
54
  }
@@ -71,12 +81,14 @@ class Blinker {
71
81
  }
72
82
  start(visible = __classPrivateFieldGet(this, _Blinker_state, "f").visible) {
73
83
  if (__classPrivateFieldGet(this, _Blinker_state, "f").timeout)
74
- this.stop();
84
+ return; // already runnning
75
85
  visible ? __classPrivateFieldGet(this, _Blinker_instances, "m", _Blinker_on).call(this) : __classPrivateFieldGet(this, _Blinker_instances, "m", _Blinker_off).call(this); // start blinking
76
86
  }
77
87
  stop() {
78
- __classPrivateFieldGet(this, _Blinker_state, "f").timeout && clearTimeout(__classPrivateFieldGet(this, _Blinker_state, "f").timeout);
79
- __classPrivateFieldGet(this, _Blinker_state, "f").timeout = null;
88
+ if (__classPrivateFieldGet(this, _Blinker_state, "f").timeout) {
89
+ clearTimeout(__classPrivateFieldGet(this, _Blinker_state, "f").timeout);
90
+ __classPrivateFieldGet(this, _Blinker_state, "f").timeout = null;
91
+ }
80
92
  }
81
93
  subscribe(fn) {
82
94
  if (!__classPrivateFieldGet(this, _Blinker_state, "f").subscribers.includes(fn)) {
@@ -88,25 +100,25 @@ class Blinker {
88
100
  }
89
101
  }
90
102
  exports.Blinker = Blinker;
91
- _Blinker_initOptions = new WeakMap(), _Blinker_state = new WeakMap(), _Blinker_instances = new WeakSet(), _Blinker_on = function _Blinker_on() {
92
- __classPrivateFieldGet(this, _Blinker_state, "f").blinks++;
103
+ _Blinker_options = new WeakMap(), _Blinker_state = new WeakMap(), _Blinker_instances = new WeakSet(), _Blinker_on = function _Blinker_on() {
93
104
  __classPrivateFieldGet(this, _Blinker_state, "f").visible = true;
94
105
  __classPrivateFieldGet(this, _Blinker_state, "f").subscribers.forEach(fn => fn(true));
95
106
  __classPrivateFieldGet(this, _Blinker_state, "f").timeout = setTimeout(() => {
96
107
  __classPrivateFieldGet(this, _Blinker_instances, "m", _Blinker_off).call(this);
97
108
  }, getPeriod(__classPrivateFieldGet(this, _Blinker_state, "f")).on);
98
109
  }, _Blinker_off = function _Blinker_off() {
99
- __classPrivateFieldGet(this, _Blinker_state, "f").blinks++;
100
110
  __classPrivateFieldGet(this, _Blinker_state, "f").visible = false;
101
111
  __classPrivateFieldGet(this, _Blinker_state, "f").subscribers.forEach(fn => fn(false));
102
112
  __classPrivateFieldGet(this, _Blinker_state, "f").timeout = setTimeout(() => {
103
113
  __classPrivateFieldGet(this, _Blinker_instances, "m", _Blinker_on).call(this);
104
114
  }, getPeriod(__classPrivateFieldGet(this, _Blinker_state, "f")).off);
105
115
  };
116
+ // ratio=1, tot=2, on=0.5, off=0.5
117
+ // ratio=2, tot=3, on=0.66, off=0.33
106
118
  function getPeriod(state) {
107
119
  const total = state.ratio + 1;
108
120
  return {
109
- on: state.period * (1 / total),
110
- off: state.period * (1 - 1 / total),
121
+ on: state.period * (1 - 1 / total),
122
+ off: state.period * (1 / total),
111
123
  };
112
124
  }
@@ -5,6 +5,7 @@ type BlinkingDigit = Digit & {
5
5
  blinkOptions?: {
6
6
  period?: Blinker['period'];
7
7
  ratio?: Blinker['ratio'];
8
+ sync?: boolean;
8
9
  };
9
10
  };
10
11
  export declare const BlinkingDigit: React.MemoExoticComponent<({ blinkOptions, className, ...rest }: BlinkingDigit) => import("react/jsx-runtime").JSX.Element>;
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  var __rest = (this && this.__rest) || function (s, e) {
26
36
  var t = {};
27
37
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -43,18 +53,18 @@ const react_1 = __importStar(require("react"));
43
53
  const clsx_1 = __importDefault(require("clsx"));
44
54
  const Digit_1 = require("../Digit");
45
55
  const Blinker_1 = require("../Blinker");
46
- const blinker = new Blinker_1.Blinker(); // singleton makes all BlinkingDigit's to blink synchronoulsy
47
56
  exports.BlinkingDigit = react_1.default.memo((_a) => {
48
57
  var { blinkOptions, className } = _a, rest = __rest(_a, ["blinkOptions", "className"]);
49
- const [visible, setVisible] = (0, react_1.useState)(blinker.visible);
58
+ const [visible, setVisible] = (0, react_1.useState)(true);
50
59
  (0, react_1.useEffect)(() => {
60
+ const blinker = new Blinker_1.Blinker(Object.assign(Object.assign({}, blinkOptions), { singleton: blinkOptions === null || blinkOptions === void 0 ? void 0 : blinkOptions.sync })); // singleton makes all instances BlinkingDigit to blink in sync
51
61
  if (blinkOptions === null || blinkOptions === void 0 ? void 0 : blinkOptions.period)
52
62
  blinker.period = blinkOptions.period;
53
63
  if (blinkOptions === null || blinkOptions === void 0 ? void 0 : blinkOptions.ratio)
54
64
  blinker.ratio = blinkOptions.ratio;
55
65
  blinker.subscribe(setVisible);
56
66
  return () => blinker.unsubscribe(setVisible);
57
- }, [blinkOptions === null || blinkOptions === void 0 ? void 0 : blinkOptions.period, blinkOptions === null || blinkOptions === void 0 ? void 0 : blinkOptions.ratio]);
67
+ }, [blinkOptions === null || blinkOptions === void 0 ? void 0 : blinkOptions.period, blinkOptions === null || blinkOptions === void 0 ? void 0 : blinkOptions.ratio, blinkOptions === null || blinkOptions === void 0 ? void 0 : blinkOptions.sync]);
58
68
  if ((blinkOptions === null || blinkOptions === void 0 ? void 0 : blinkOptions.period) === 0 ||
59
69
  (blinkOptions === null || blinkOptions === void 0 ? void 0 : blinkOptions.ratio) === 0 ||
60
70
  typeof (rest === null || rest === void 0 ? void 0 : rest.off) === 'boolean')
@@ -21,7 +21,7 @@ const useStyleInjection_1 = __importDefault(require("./useStyleInjection"));
21
21
  const digit_css_js_1 = __importDefault(require("./digit.css.js"));
22
22
  const Digit = (_a) => {
23
23
  var rest = __rest(_a, []);
24
- const scopeAttribute = (0, useStyleInjection_1.default)(digit_css_js_1.default.content, digit_css_js_1.default.hash);
24
+ const scopeAttribute = (0, useStyleInjection_1.default)(digit_css_js_1.default.content, digit_css_js_1.default.hash, []);
25
25
  return ((0, jsx_runtime_1.jsx)("div", Object.assign({}, scopeAttribute, { style: { display: 'contents' }, children: (0, jsx_runtime_1.jsx)(UnstyledDigit_1.Digit, Object.assign({}, rest)) })));
26
26
  };
27
27
  exports.Digit = Digit;
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+ import type { StoryObj } from '@storybook/react';
3
+ import { Digit } from '../';
4
+ declare const meta: {
5
+ title: string;
6
+ component: ({ ...rest }: Digit) => import("react/jsx-runtime").JSX.Element;
7
+ tags: string[];
8
+ parameters: {
9
+ layout: string;
10
+ };
11
+ argTypes: {
12
+ off: {
13
+ control: "boolean";
14
+ };
15
+ };
16
+ };
17
+ export default meta;
18
+ type Story = StoryObj<typeof meta>;
19
+ export type DisplayProps = React.HTMLAttributes<HTMLDivElement> & {
20
+ scale?: number;
21
+ segmentStyle?: Digit['segmentStyle'];
22
+ value: string;
23
+ };
24
+ export declare const Clock: Story;
25
+ export declare const Digits: Story;
26
+ export declare const Blinking: Story;
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.Blinking = exports.Digits = exports.Clock = void 0;
15
+ const jsx_runtime_1 = require("react/jsx-runtime");
16
+ const react_1 = require("react");
17
+ const __1 = require("../");
18
+ const _1 = require("./");
19
+ const meta = {
20
+ title: 'Example/Digit',
21
+ component: __1.Digit,
22
+ tags: ['autodocs'],
23
+ parameters: {
24
+ layout: 'fullscreen', // https://storybook.js.org/docs/configure/story-layout
25
+ },
26
+ argTypes: {
27
+ off: { control: 'boolean' },
28
+ },
29
+ };
30
+ exports.default = meta;
31
+ const grid = {
32
+ display: 'flex',
33
+ gap: '.35rem',
34
+ padding: '1rem',
35
+ placeItems: 'center center',
36
+ };
37
+ const CustomDigit = (_a) => {
38
+ var rest = __rest(_a, []);
39
+ return ((0, jsx_runtime_1.jsx)(__1.Digit, Object.assign({}, rest, { shape: "pill", segmentStyle: {
40
+ thickness: '.25rem',
41
+ length: '1.5rem',
42
+ spacing: '0.25rem',
43
+ filament: '.0625rem',
44
+ } })));
45
+ };
46
+ const DigitTest = () => {
47
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("style", { children: `.digit { outline: 0.1px solid rgba(255, 0, 0, 0.2); }` }), (0, jsx_runtime_1.jsxs)("div", { style: grid, children: [(0, jsx_runtime_1.jsx)(__1.Digit, { value: 0, className: "test" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: 1, shape: "round", segmentStyle: {
48
+ thickness: '.35rem',
49
+ color: 'green',
50
+ colorOff: 'blue',
51
+ } }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: 2, shape: "pill", segmentStyle: { thickness: '.5rem' } }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: 3, shape: "rect", segmentStyle: { spacing: '.25rem' } }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: 4, style: { color: 'red' } }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: ":" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: 5 }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: 6 }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: 7 }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: 8, off: true }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: 9 }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "." }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "pm" })] }), (0, jsx_runtime_1.jsxs)("div", { style: grid, children: [(0, jsx_runtime_1.jsx)(__1.BlinkingDigit, { value: "pm", blinkOptions: { period: 2000 } }), (0, jsx_runtime_1.jsx)(__1.BlinkingDigit, { value: ":", shape: "round" }), (0, jsx_runtime_1.jsx)(__1.BlinkingDigit, { value: "pm", shape: "rect" }), (0, jsx_runtime_1.jsx)(__1.BlinkingDigit, { value: "am", shape: "round" }), (0, jsx_runtime_1.jsx)(__1.BlinkingDigit, { value: ":", shape: "pill" }), (0, jsx_runtime_1.jsx)(__1.BlinkingDigit, { value: "pm", shape: "pill" }), (0, jsx_runtime_1.jsx)(__1.BlinkingDigit, { value: "-", shape: "pill" }), (0, jsx_runtime_1.jsx)(__1.BlinkingDigit, { value: "_", shape: "pill" }), (0, jsx_runtime_1.jsx)(__1.BlinkingDigit, { value: 2, shape: "pill", segmentStyle: { thickness: '.5rem' } }), (0, jsx_runtime_1.jsx)(__1.BlinkingDigit, { value: ":", shape: "pill", segmentStyle: { thickness: '1rem' } })] }), (0, jsx_runtime_1.jsxs)("div", { style: grid, children: [(0, jsx_runtime_1.jsx)(__1.Digit, { value: "A" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "C" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "E" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "F" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "G" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "H" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "J" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "L" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "O" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "P" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "S" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "U" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "Y" })] }), (0, jsx_runtime_1.jsxs)("div", { style: grid, children: [(0, jsx_runtime_1.jsx)(__1.Digit, { value: "c" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "b" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "d" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "h" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "n" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "o" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "r" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "u" })] }), (0, jsx_runtime_1.jsxs)("div", { style: grid, children: [(0, jsx_runtime_1.jsx)(CustomDigit, { value: 0 }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: 1 }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: ":" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: 2 }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: 3 }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "am" })] }), (0, jsx_runtime_1.jsxs)("div", { style: grid, children: [(0, jsx_runtime_1.jsx)(__1.Digit, { value: "E" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "r" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "r" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "o" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "r" }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "." })] }), (0, jsx_runtime_1.jsxs)("div", { style: grid, children: [(0, jsx_runtime_1.jsx)(CustomDigit, { value: "A" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "C" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "E" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "F" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "H" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "J" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "L" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "O" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "P" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "U" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "Y" })] }), (0, jsx_runtime_1.jsxs)("div", { style: grid, children: [(0, jsx_runtime_1.jsx)(CustomDigit, { value: "c" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "b" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "d" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "h" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "n" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "o" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "r" }), (0, jsx_runtime_1.jsx)(CustomDigit, { value: "u" }), (0, jsx_runtime_1.jsx)(__1.BlinkingDigit, { value: "2", shape: "round", segmentStyle: {
52
+ color: 'green',
53
+ colorOff: 'red',
54
+ length: '1.5rem',
55
+ spacing: '-0.025rem',
56
+ thickness: '0.5rem',
57
+ opacityOff: 0.2,
58
+ } })] })] }));
59
+ };
60
+ const charset = new Set(Object.keys(_1.charToSevenSegments));
61
+ function setCharAt(str, index, chr) {
62
+ if (index > str.length - 1)
63
+ return str;
64
+ return str.substr(0, index) + chr + str.substr(index + 1);
65
+ }
66
+ const BlinkingDigitTest = () => {
67
+ const input = (0, react_1.useRef)(null);
68
+ const [dgts, setDgts] = (0, react_1.useState)('');
69
+ const addDigit = () => {
70
+ if (input.current.value) {
71
+ setDgts(prev => prev + input.current.value);
72
+ }
73
+ };
74
+ const removeDigit = (idx) => {
75
+ const next = setCharAt(dgts, idx, '');
76
+ setDgts(next);
77
+ };
78
+ const handleChange = () => {
79
+ if (!charset.has(input.current.value)) {
80
+ input.current.value = '';
81
+ }
82
+ };
83
+ const handleInputKeypress = (e) => {
84
+ if (e.key === 'Enter') {
85
+ addDigit();
86
+ }
87
+ };
88
+ (0, react_1.useEffect)(() => {
89
+ var _a;
90
+ (_a = input.current) === null || _a === void 0 ? void 0 : _a.addEventListener('keydown', handleInputKeypress);
91
+ return () => {
92
+ var _a;
93
+ (_a = input.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('keydown', handleInputKeypress);
94
+ };
95
+ }, []);
96
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("style", { children: `
97
+ .digit { outline: 0.1px solid rgba(255, 0, 0, 0.2); }
98
+ input { border: 1px solid black; border-radius: .5rem; padding: .5rem .25rem;}
99
+ button { border: none; border-radius: .5rem; padding: .5rem 1rem;}
100
+ button, input, p { font-size: 100%; font-family: sans-serif; margin: .25rem;}
101
+ ` }), (0, jsx_runtime_1.jsxs)("p", { children: ["charset: ", Array.from(charset).join(', ')] }), (0, jsx_runtime_1.jsx)("input", { type: "text", placeholder: "digit", ref: input, onChange: handleChange, maxLength: 1 }), (0, jsx_runtime_1.jsx)("button", { onClick: addDigit, children: "Add digit" }), (0, jsx_runtime_1.jsxs)("div", { style: grid, children: [(0, jsx_runtime_1.jsx)(__1.Digit, { value: "8", segmentStyle: { thickness: '.35rem' } }), (0, jsx_runtime_1.jsx)(__1.Digit, { value: "b" }), (0, jsx_runtime_1.jsx)(__1.BlinkingDigit, { value: ":", blinkOptions: {
102
+ period: 2000,
103
+ ratio: 3,
104
+ } }), dgts.split('').map((char, idx) => ((0, jsx_runtime_1.jsx)(__1.BlinkingDigit, { value: char, onClick: () => removeDigit(idx), segmentStyle: {
105
+ transitionDuration: '0.5s',
106
+ }, blinkOptions: { sync: false } }, idx)))] })] }));
107
+ };
108
+ const getDigits = (str) => {
109
+ let s = str.trim().toLowerCase();
110
+ const am = s.includes('am');
111
+ const pm = s.includes('pm');
112
+ s = s.replace('am', '').replace('pm', '').replace(' ', '');
113
+ const result = s.split('');
114
+ if (am)
115
+ result.push('am');
116
+ if (pm)
117
+ result.push('pm');
118
+ return result;
119
+ };
120
+ const Display = (_a) => {
121
+ var { scale = 1, value } = _a, rest = __rest(_a, ["scale", "value"]);
122
+ const digits = getDigits(value);
123
+ return ((0, jsx_runtime_1.jsx)("div", Object.assign({}, rest, { children: digits.map((digit, idx) => {
124
+ const props = {
125
+ value: digit,
126
+ style: {
127
+ fontSize: `${scale * 100}%`,
128
+ },
129
+ segmentStyle: {
130
+ color: 'green',
131
+ cornerShift: 'calc(var(--thickness) / 8)',
132
+ },
133
+ };
134
+ if (digit === ':') {
135
+ return (0, jsx_runtime_1.jsx)(__1.BlinkingDigit, Object.assign({}, props), idx);
136
+ }
137
+ else {
138
+ return (0, jsx_runtime_1.jsx)(__1.Digit, Object.assign({}, props), idx);
139
+ }
140
+ }) })));
141
+ };
142
+ const getTime = () => new Date().toLocaleTimeString();
143
+ const SimpleClock = () => {
144
+ const [time, setTime] = (0, react_1.useState)(getTime());
145
+ const blinker = new __1.Blinker();
146
+ blinker.period = 2000;
147
+ blinker.ratio = 1;
148
+ const handleBlinkerChange = () => setTime(getTime());
149
+ (0, react_1.useEffect)(() => {
150
+ blinker.subscribe(handleBlinkerChange);
151
+ return () => blinker.unsubscribe(handleBlinkerChange);
152
+ }, []);
153
+ return (0, jsx_runtime_1.jsx)(Display, { scale: 2, style: grid, value: time });
154
+ };
155
+ exports.Clock = {
156
+ args: {
157
+ value: '0',
158
+ },
159
+ render: SimpleClock,
160
+ };
161
+ exports.Digits = {
162
+ args: {
163
+ value: '0',
164
+ },
165
+ render: DigitTest,
166
+ };
167
+ exports.Blinking = {
168
+ args: {
169
+ value: '0',
170
+ },
171
+ render: BlinkingDigitTest,
172
+ };
@@ -18,6 +18,7 @@ type SegmentStyle = {
18
18
  opacityOn?: CSSProperties['opacity'];
19
19
  opacityOff?: CSSProperties['opacity'];
20
20
  transitionDuration?: CSSProperties['transitionDuration'];
21
+ cornerShift?: CSSProperties['width'];
21
22
  };
22
23
  export type Digit = DivProps & DigitProps & {
23
24
  segmentStyle?: SegmentStyle;
@@ -23,7 +23,7 @@ const Digit = (_a) => {
23
23
  var { segmentStyle, value } = _a, rest = __rest(_a, ["segmentStyle", "value"]);
24
24
  const type = valueToType(value);
25
25
  const segments = type && valueToSegments(value); // {A: true, ...}
26
- const sx = Object.assign({ '--segment-color': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.color, '--segment-color-off': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.colorOff, '--segment-thickness': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.thickness, '--segment-spacing': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.spacing, '--segment-length': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.length, '--segment-filament': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.filament, '--segment-opacity-on': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.opacityOn, '--segment-opacity-off': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.opacityOff, '--segment-transition-duration': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.transitionDuration }, rest.style);
26
+ const sx = Object.assign({ '--segment-color': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.color, '--segment-color-off': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.colorOff, '--segment-thickness': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.thickness, '--segment-spacing': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.spacing, '--segment-length': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.length, '--segment-filament': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.filament, '--segment-opacity-on': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.opacityOn, '--segment-opacity-off': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.opacityOff, '--segment-transition-duration': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.transitionDuration, '--segment-corner-shift': segmentStyle === null || segmentStyle === void 0 ? void 0 : segmentStyle.cornerShift }, rest.style);
27
27
  if (type === 'digit')
28
28
  return (0, jsx_runtime_1.jsx)(components_1.DigitSegments, Object.assign({}, rest, segments, { style: sx }));
29
29
  if (type === 'colon')
@@ -32,7 +32,7 @@ const Digit = (_a) => {
32
32
  return (0, jsx_runtime_1.jsx)(components_1.AmpmSegments, Object.assign({}, rest, segments, { style: sx }));
33
33
  if (type === 'dot')
34
34
  return (0, jsx_runtime_1.jsx)(components_1.DotSegments, Object.assign({}, rest, segments, { style: sx }));
35
- console.warn(`Digit.tsx: incompatible value: ${value.toString()}`);
35
+ console.warn(`(at Digit.tsx) incompatible value: ${value.toString()}`);
36
36
  return (0, jsx_runtime_1.jsx)("div", Object.assign({}, rest, { className: (0, clsx_1.default)('digit unknown', rest.className) }));
37
37
  };
38
38
  exports.Digit = Digit;
@@ -9,20 +9,21 @@
9
9
  .digit {
10
10
  --color: var(--segment-color, currentColor);
11
11
  --color-off: var(--segment-color-off, var(--color));
12
- --thick: var(--segment-thickness, 0.25rem); /* =4px */
13
- --length: var(--segment-length, 1rem);
14
- --spacing: var(--segment-spacing, 0.0625rem); /* =1px */
15
- --filament: var(--segment-filament, 0rem); /* vertical squeeze for A, D */
12
+ --thickness: var(--segment-thickness, 0.25em); /* =4px */
13
+ --length: var(--segment-length, 1em);
14
+ --spacing: var(--segment-spacing, 0.0625em); /* =1px */
15
+ --filament: var(--segment-filament, 0em); /* vertical squeeze for A, D */
16
16
  --opacity-on: var(--segment-opacity-on, 1);
17
17
  --opacity-off: var(--segment-opacity-off, 0.1);
18
18
  --transition-duration: var(--segment-transition-duration, 0.25s);
19
- /* distortion of diamond, -0.5...0.5 */
20
- --corner-shift: var(--diamond-corner-shift, 0.2);
19
+ /* distortion of diamond corners */
20
+ --corner-shift: var(--segment-corner-shift, 0em);
21
21
 
22
22
  --svg-am: url('data:image/svg+xml,<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 16 16" xml:space="preserve"><style type="text/css">.st0{fill:none;stroke:black;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:10;stroke-width:1;}</style><polyline class="st0" points="1.4,11.5 1.4,11.4 3.8,3.5 4.2,3.5 6.6,11.4 6.6,11.5 "/><polyline class="st0" points="14.5,11.5 14.5,3.5 14.1,3.5 11.5,9.9 11.3,9.9 8.9,3.5 8.5,3.5 8.5,11.5 "/><line class="st0" x1="2.6" y1="9.5" x2="5.4" y2="9.5"/></svg>');
23
23
  --svg-pm: url('data:image/svg+xml,<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 16 16" xml:space="preserve"><style type="text/css">.st0{fill:none;stroke:black;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:10;stroke-width:1;}</style><path class="st0" d="M1.5,11.5V3.4h2.1c1.6,0,2.5,1,2.5,2.2s-1,2.3-2.5,2.3H2.2"/><polyline class="st0" points="14.5,11.5 14.5,3.5 14.1,3.5 11.5,9.9 11.3,9.9 8.9,3.5 8.5,3.5 8.5,11.5 "/></svg>');
24
24
 
25
25
  /* computed values */
26
+ --thick: var(--thickness);
26
27
  --digit-width: calc(var(--length) + var(--thick) + var(--spacing));
27
28
  --digit-height: calc(var(--length) * 2 + var(--thick) + var(--spacing) * 2);
28
29
 
@@ -91,7 +92,7 @@
91
92
  /* segments */
92
93
  .segment {
93
94
  --th-half-100: calc(100% - var(--th-half));
94
- --shft: calc(var(--thick) * var(--corner-shift));
95
+ --shft: var(--corner-shift);
95
96
 
96
97
  background-color: var(--color);
97
98
  display: block;
@@ -0,0 +1,333 @@
1
+ /* This file is auto-generated */
2
+
3
+ const css = {
4
+ src: `src/Digit/digit.css`,
5
+ hash: `21rs68w6m0r`,
6
+ content: `
7
+ /**
8
+ * A
9
+ * F B D2 AM
10
+ * G
11
+ * E C D1 PM
12
+ * D DP
13
+ */
14
+
15
+ .digit {
16
+ --color: var(--segment-color, currentColor);
17
+ --color-off: var(--segment-color-off, var(--color));
18
+ --thickness: var(--segment-thickness, 0.25em); /* =4px */
19
+ --length: var(--segment-length, 1em);
20
+ --spacing: var(--segment-spacing, 0.0625em); /* =1px */
21
+ --filament: var(--segment-filament, 0em); /* vertical squeeze for A, D */
22
+ --opacity-on: var(--segment-opacity-on, 1);
23
+ --opacity-off: var(--segment-opacity-off, 0.1);
24
+ --transition-duration: var(--segment-transition-duration, 0.25s);
25
+ /* distortion of diamond corners */
26
+ --corner-shift: var(--segment-corner-shift, 0em);
27
+
28
+ --svg-am: url('data:image/svg+xml,<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 16 16" xml:space="preserve"><style type="text/css">.st0{fill:none;stroke:black;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:10;stroke-width:1;}</style><polyline class="st0" points="1.4,11.5 1.4,11.4 3.8,3.5 4.2,3.5 6.6,11.4 6.6,11.5 "/><polyline class="st0" points="14.5,11.5 14.5,3.5 14.1,3.5 11.5,9.9 11.3,9.9 8.9,3.5 8.5,3.5 8.5,11.5 "/><line class="st0" x1="2.6" y1="9.5" x2="5.4" y2="9.5"/></svg>');
29
+ --svg-pm: url('data:image/svg+xml,<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 16 16" xml:space="preserve"><style type="text/css">.st0{fill:none;stroke:black;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:10;stroke-width:1;}</style><path class="st0" d="M1.5,11.5V3.4h2.1c1.6,0,2.5,1,2.5,2.2s-1,2.3-2.5,2.3H2.2"/><polyline class="st0" points="14.5,11.5 14.5,3.5 14.1,3.5 11.5,9.9 11.3,9.9 8.9,3.5 8.5,3.5 8.5,11.5 "/></svg>');
30
+
31
+ /* computed values */
32
+ --thick: var(--thickness);
33
+ --digit-width: calc(var(--length) + var(--thick) + var(--spacing));
34
+ --digit-height: calc(var(--length) * 2 + var(--thick) + var(--spacing) * 2);
35
+
36
+ --thick-minus: calc(var(--thick) * -1);
37
+ --th-half: calc(var(--thick) / 2);
38
+ --th-half-minus: calc(var(--th-half) * -1);
39
+ --spacing-minus: calc(var(--spacing) * -1);
40
+ --sp-half: calc(var(--spacing) / 2);
41
+ --sp-half-minus: calc(var(--sp-half) * -1);
42
+
43
+ --radius-round: calc(var(--thick) * 0.33);
44
+ --radius-pill: 100em;
45
+
46
+ display: inline-block;
47
+ position: relative;
48
+ width: var(--digit-width);
49
+ height: var(--digit-height);
50
+
51
+ /* prevents flex-shrink effect */
52
+ min-width: var(--digit-width);
53
+ min-height: var(--digit-height);
54
+
55
+ &.unknown {
56
+ width: var(--thick);
57
+ min-width: var(--thick);
58
+ }
59
+
60
+ .opacity-wrapper {
61
+ position: absolute;
62
+ width: 100%;
63
+ height: 100%;
64
+ }
65
+
66
+ .opacity-wrapper,
67
+ .opacity-wrapper .segment {
68
+ transition-property: background-color, border-color, opacity, visibility;
69
+ transition-duration: var(--transition-duration);
70
+ }
71
+
72
+ .opacity-wrapper.off.on .segment.off,
73
+ .opacity-wrapper.on .segment.off,
74
+ .opacity-wrapper.off .segment.on {
75
+ visibility: hidden;
76
+ }
77
+ .opacity-wrapper.off .segment.off,
78
+ .opacity-wrapper.on .segment.on {
79
+ visibility: visible;
80
+ }
81
+
82
+ .opacity-wrapper.on {
83
+ opacity: var(--opacity-on);
84
+ }
85
+ .opacity-wrapper.off {
86
+ opacity: var(--opacity-off);
87
+ }
88
+ .opacity-wrapper.off.on {
89
+ opacity: 0;
90
+ }
91
+ .opacity-wrapper.on:not(.off) .segment.on {
92
+ opacity: 1;
93
+ }
94
+ .opacity-wrapper.on:not(.off) .segment.off {
95
+ opacity: 0;
96
+ }
97
+
98
+ /* segments */
99
+ .segment {
100
+ --th-half-100: calc(100% - var(--th-half));
101
+ --shft: var(--corner-shift);
102
+
103
+ background-color: var(--color);
104
+ display: block;
105
+ position: absolute;
106
+
107
+ &.segment.off {
108
+ background-color: var(--color-off);
109
+ border-color: var(--color-off);
110
+ }
111
+ /* vertical segments */
112
+ &.vertical {
113
+ width: var(--thick);
114
+ height: var(--length);
115
+ left: 0;
116
+
117
+ &.B,
118
+ &.C {
119
+ left: auto;
120
+ right: 0;
121
+ }
122
+ }
123
+ &.E,
124
+ &.C {
125
+ bottom: calc(var(--th-half) + var(--sp-half));
126
+ }
127
+ &.F,
128
+ &.B {
129
+ top: calc(var(--th-half) + var(--sp-half));
130
+ }
131
+
132
+ /* horizontal segments */
133
+ &.horizontal {
134
+ width: var(--length);
135
+ height: var(--thick);
136
+ left: calc(var(--th-half) + var(--sp-half));
137
+
138
+ &.A,
139
+ &.D {
140
+ width: calc(var(--length) + var(--shft) * 2);
141
+ left: calc(var(--th-half) + var(--sp-half) - var(--shft));
142
+ }
143
+ &.A {
144
+ top: calc(var(--filament) + var(--shft));
145
+ }
146
+ &.D {
147
+ bottom: calc(var(--filament) + var(--shft));
148
+ }
149
+ &.G {
150
+ bottom: calc(var(--length) + var(--spacing));
151
+ }
152
+ }
153
+
154
+ /* spearheads */
155
+ &.horizontal {
156
+ clip-path: polygon(
157
+ 0 50%,
158
+ var(--th-half) 0,
159
+ var(--th-half-100) 0,
160
+ 100% 50%,
161
+ var(--th-half-100) 100%,
162
+ var(--th-half) 100%
163
+ );
164
+ &.A {
165
+ /* x y */
166
+ clip-path: polygon(
167
+ 0 calc(50% - var(--shft)),
168
+ calc(var(--th-half) - var(--shft)) 0,
169
+ calc(var(--th-half-100) + var(--shft)) 0,
170
+ 100% calc(50% - var(--shft)),
171
+ calc(var(--th-half-100) - var(--shft)) 100%,
172
+ calc(var(--th-half) + var(--shft)) 100%
173
+ );
174
+ }
175
+ &.D {
176
+ /* x y */
177
+ clip-path: polygon(
178
+ 0 calc(50% + var(--shft)),
179
+ calc(var(--th-half) + var(--shft)) 0,
180
+ calc(var(--th-half-100) - var(--shft)) 0,
181
+ 100% calc(50% + var(--shft)),
182
+ calc(var(--th-half-100) + var(--shft)) 100%,
183
+ calc(var(--th-half) - var(--shft)) 100%
184
+ );
185
+ }
186
+ }
187
+ &.vertical {
188
+ clip-path: polygon(
189
+ 50% 0,
190
+ 0 var(--th-half),
191
+ 0 var(--th-half-100),
192
+ 50% 100%,
193
+ 100% var(--th-half-100),
194
+ 100% var(--th-half)
195
+ );
196
+ &.B {
197
+ /* x y */
198
+ clip-path: polygon(
199
+ calc(50% + var(--shft)) 0,
200
+ 0 calc(var(--th-half) + var(--shft)),
201
+ 0 var(--th-half-100),
202
+ 50% 100%,
203
+ 100% var(--th-half-100),
204
+ 100% calc(var(--th-half) - var(--shft))
205
+ );
206
+ }
207
+ &.C {
208
+ /* x y */
209
+ clip-path: polygon(
210
+ 50% 0,
211
+ 0 var(--th-half),
212
+ 0 calc(var(--th-half-100) - var(--shft)),
213
+ calc(50% + var(--shft)) 100%,
214
+ 100% calc(var(--th-half-100) + var(--shft)),
215
+ 100% var(--th-half)
216
+ );
217
+ }
218
+ &.E {
219
+ /* x y */
220
+ clip-path: polygon(
221
+ 50% 0,
222
+ 0 var(--th-half),
223
+ 0 calc(var(--th-half-100) + var(--shft)),
224
+ calc(50% - var(--shft)) 100%,
225
+ 100% calc(var(--th-half-100) - var(--shft)),
226
+ 100% var(--th-half)
227
+ );
228
+ }
229
+ &.F {
230
+ /* x y */
231
+ clip-path: polygon(
232
+ calc(50% - var(--shft)) 0,
233
+ 0 calc(var(--th-half) - var(--shft)),
234
+ 0 var(--th-half-100),
235
+ 50% 100%,
236
+ 100% var(--th-half-100),
237
+ 100% calc(var(--th-half) + var(--shft))
238
+ );
239
+ }
240
+ }
241
+ }
242
+
243
+ /* segment shapes */
244
+ &.shape-rect .segment.segment {
245
+ clip-path: unset;
246
+ }
247
+ &.shape-round .segment.segment {
248
+ border-radius: var(--radius-round);
249
+ clip-path: unset;
250
+ }
251
+ &.shape-pill .segment.segment {
252
+ border-radius: var(--radius-pill);
253
+ clip-path: unset;
254
+ }
255
+
256
+ &.ampm {
257
+ --digit-width: calc(var(--length) + var(--thick) + var(--spacing));
258
+
259
+ .segment {
260
+ background: var(--color);
261
+ width: var(--digit-width);
262
+ height: var(--length);
263
+
264
+ mask-origin: fill-box;
265
+ mask-position: center;
266
+ mask-repeat: no-repeat;
267
+ mask-size:
268
+ auto 85%,
269
+ contain;
270
+ }
271
+
272
+ .AM {
273
+ bottom: calc(var(--digit-height) / 2 + var(--thick) / 4);
274
+ mask-image: var(--svg-am);
275
+ }
276
+ &.shape-rect .AM,
277
+ &.shape-pill .AM,
278
+ &.shape-round .AM {
279
+ mask-composite: exclude;
280
+ mask-image: var(--svg-am), linear-gradient(var(--color) 0 0);
281
+ }
282
+ .PM {
283
+ top: calc(var(--digit-height) / 2 + var(--thick) / 4);
284
+ mask-image: var(--svg-pm);
285
+ }
286
+ &.shape-rect .PM,
287
+ &.shape-pill .PM,
288
+ &.shape-round .PM {
289
+ mask-composite: exclude;
290
+ mask-image: var(--svg-pm), linear-gradient(var(--color) 0 0);
291
+ }
292
+ &.shape-round .segment {
293
+ border-radius: var(--radius-round);
294
+ }
295
+ &.shape-pill .segment {
296
+ border-radius: var(--radius-pill);
297
+ }
298
+ }
299
+
300
+ &.dot,
301
+ &.colon {
302
+ --digit-width: calc(var(--thick) * 3);
303
+
304
+ & .segment {
305
+ --dot-border-width: calc(var(--thick) * 0.6);
306
+
307
+ border: var(--dot-border-width) solid var(--color); /* dot made from border to have same size on zoom */
308
+ position: absolute;
309
+ width: 0;
310
+ height: 0;
311
+ left: calc(var(--digit-width) / 2 - var(--dot-border-width));
312
+ }
313
+ /* lower part of a colon */
314
+ .segment.D1 {
315
+ top: calc(var(--digit-height) / 3 - var(--thick) / 2);
316
+ }
317
+ /* upper part of a colon */
318
+ .segment.D2 {
319
+ bottom: calc(var(--digit-height) / 3 - var(--thick) / 2);
320
+ }
321
+ /* dot itself */
322
+ .segment.DP {
323
+ bottom: 0;
324
+ }
325
+ &.shape-default .segment {
326
+ border-radius: var(--radius-pill);
327
+ }
328
+ }
329
+ }
330
+ `,
331
+ };
332
+
333
+ export default css;
@@ -1,4 +1,16 @@
1
- declare const useHeadStyleInjection: (css: string, id: string, dependencies?: never[], scoped?: boolean) => {
2
- "data-style-scope-id": string;
1
+ type Style = {
2
+ id: string;
3
+ content: string;
3
4
  };
5
+ declare const useHeadStyleInjection: (css: string, cssHash: string, dependencies?: never[], scoped?: boolean) => {
6
+ [x: string]: boolean | undefined;
7
+ };
8
+ export declare class StyleInjector {
9
+ #private;
10
+ private static instance;
11
+ constructor();
12
+ add(s: Style): void;
13
+ remove(s: Style): void;
14
+ has(s: Style): boolean;
15
+ }
4
16
  export default useHeadStyleInjection;
@@ -4,67 +4,84 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
4
4
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
5
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
6
  };
7
- var _StyleInjectionState_state;
7
+ var _StyleInjector_state;
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.StyleInjector = void 0;
9
10
  const react_1 = require("react");
10
- const scopeAttribute = 'data-style-scope-id';
11
+ const scopeAttributePrefix = 'data-style-scope-';
11
12
  // Runtime style injection
12
- const useHeadStyleInjection = (css, id, dependencies = [], scoped = true // isolate css behind @scope
13
+ const useHeadStyleInjection = (css, cssHash, dependencies = [], scoped = true // isolate css behind @scope
13
14
  ) => {
14
- const injected = new StyleInjectionState(); // singleton's state
15
- const _id = `_${id}`; // safe id to make CSS selectors work
15
+ const injector = new StyleInjector(); // singleton!
16
+ const scopeAttribute = `${scopeAttributePrefix}-${cssHash}`;
16
17
  const style = {
17
- id: `inject_id_${_id}`, // hash of css content
18
- css: scoped ? wrapWithScope(css, _id) : css,
18
+ id: `css_id__${cssHash}`,
19
+ content: scoped ? wrapWithScope(css, scopeAttribute) : css,
19
20
  };
20
21
  (0, react_1.useInsertionEffect)(() => {
21
- injected.add(style);
22
- return () => injected.remove(style);
22
+ injector.add(style);
23
+ return () => injector.remove(style);
23
24
  }, dependencies);
24
25
  return {
25
- [scopeAttribute]: _id,
26
+ [scopeAttribute]: scoped ? true : undefined,
26
27
  };
27
28
  };
28
- class StyleInjectionState {
29
+ class StyleInjector {
29
30
  constructor() {
30
- _StyleInjectionState_state.set(this, {
31
- injected: new Set(),
32
- });
33
- if (!StyleInjectionState.instance) {
34
- StyleInjectionState.instance = this; // create first instance if needed
31
+ _StyleInjector_state.set(this, new Map());
32
+ if (!StyleInjector.instance) {
33
+ StyleInjector.instance = this;
35
34
  }
36
- return StyleInjectionState.instance;
35
+ return StyleInjector.instance;
37
36
  }
38
37
  add(s) {
39
- if (!this.has(s)) {
40
- __classPrivateFieldGet(this, _StyleInjectionState_state, "f").injected.add(s.id);
41
- document.head.appendChild(createStyleElement(s.css, s.id));
38
+ if (this.has(s)) {
39
+ const count = __classPrivateFieldGet(this, _StyleInjector_state, "f").get(s.id) + 1;
40
+ __classPrivateFieldGet(this, _StyleInjector_state, "f").set(s.id, count);
41
+ }
42
+ else {
43
+ __classPrivateFieldGet(this, _StyleInjector_state, "f").set(s.id, 1);
44
+ }
45
+ if (__classPrivateFieldGet(this, _StyleInjector_state, "f").get(s.id) === 1) {
46
+ document.head.appendChild(createStyleElement(s));
42
47
  }
43
48
  }
44
49
  remove(s) {
45
50
  var _a;
46
51
  if (this.has(s)) {
47
- __classPrivateFieldGet(this, _StyleInjectionState_state, "f").injected.delete(s.id);
52
+ const count = __classPrivateFieldGet(this, _StyleInjector_state, "f").get(s.id) - 1;
53
+ __classPrivateFieldGet(this, _StyleInjector_state, "f").set(s.id, count);
54
+ }
55
+ else {
56
+ console.warn(`(at useStyleInjection.ts) unable to remove style: ${s.id}`);
57
+ }
58
+ if (__classPrivateFieldGet(this, _StyleInjector_state, "f").get(s.id) === 0) {
48
59
  (_a = document.head.querySelector(`#${s.id}`)) === null || _a === void 0 ? void 0 : _a.remove();
49
60
  }
50
61
  }
51
62
  has(s) {
52
- return __classPrivateFieldGet(this, _StyleInjectionState_state, "f").injected.has(s.id);
63
+ return __classPrivateFieldGet(this, _StyleInjector_state, "f").has(s.id);
53
64
  }
54
65
  }
55
- _StyleInjectionState_state = new WeakMap();
56
- const createStyleElement = (content, id = '') => {
66
+ exports.StyleInjector = StyleInjector;
67
+ _StyleInjector_state = new WeakMap();
68
+ const createStyleElement = (style) => {
57
69
  const el = document.createElement('style');
58
- el.innerHTML = content;
59
- if (id !== '')
60
- el.id = id;
70
+ el.innerHTML = style.content;
71
+ if (style.id !== '')
72
+ el.id = style.id;
61
73
  return el;
62
74
  };
63
- const wrapWithScope = (rules, _id) => {
64
- const isolated = `@scope ([${scopeAttribute}=${_id}]) {
65
- :scope { display: contents; }
66
- ${rules}
67
- }`;
75
+ const wrapWithScope = (css, scopeAttribute) => {
76
+ // unused bc @scope at-rule does not work in Firefox
77
+ const scoped = `@scope ([${scopeAttribute}]) {` +
78
+ `:scope { display: contents; }` +
79
+ `${css}` +
80
+ `}`;
81
+ const isolated = `[${scopeAttribute}] { display: contents; }` +
82
+ `[${scopeAttribute}] {` +
83
+ `${css}` +
84
+ `}`;
68
85
  return isolated;
69
86
  };
70
87
  exports.default = useHeadStyleInjection;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-led-digit",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "react component for 7-segment display (digit), includes dot, colon and am-pm digits",
5
5
  "main": "./lib/index.js",
6
6
  "files": [
@@ -11,7 +11,7 @@
11
11
  "build-storybook": "storybook build",
12
12
  "build-ts": "tsc --project tsconfig.build.json",
13
13
  "clean": "rimraf lib",
14
- "css-copy": "npx cpy src/**/*.css lib",
14
+ "css-copy": "npx cpy src/**/*.css lib && npx cpy src/**/*.css.* lib",
15
15
  "css-to-js-watch": "node css-to-js --watch",
16
16
  "css-to-js": "node css-to-js",
17
17
  "dev": "npm-run-all --parallel storybook css-to-js-watch",
@@ -36,16 +36,9 @@
36
36
  "engines": {
37
37
  "node": ">=12.0"
38
38
  },
39
- "keywords": [
40
- "7-segment",
41
- "led",
42
- "digit",
43
- "react",
44
- "component",
45
- "seven-segments",
46
- "display",
47
- "clock"
48
- ],
39
+ "dependencies": {
40
+ "clsx": "^2.1.1"
41
+ },
49
42
  "devDependencies": {
50
43
  "@chromatic-com/storybook": "^1.6.1",
51
44
  "@storybook/addon-essentials": "^8.2.4",
@@ -61,7 +54,6 @@
61
54
  "@typescript-eslint/eslint-plugin": "^7.16.1",
62
55
  "@typescript-eslint/parser": "^7.16.1",
63
56
  "chokidar": "^4.0.1",
64
- "clsx": "^2.1.1",
65
57
  "cpy-cli": "^5.0.0",
66
58
  "eslint": "^8.57.0",
67
59
  "eslint-config-prettier": "^9.1.0",
@@ -79,6 +71,16 @@
79
71
  "ts-jest": "^29.2.3",
80
72
  "typescript": "^5.5.3"
81
73
  },
74
+ "keywords": [
75
+ "7-segment",
76
+ "led",
77
+ "digit",
78
+ "react",
79
+ "component",
80
+ "seven-segments",
81
+ "display",
82
+ "clock"
83
+ ],
82
84
  "lint-staged": {
83
85
  "*.ts": "eslint --cache --cache-location .eslintcache --fix"
84
86
  },