@homecode/ui 5.7.0 → 5.7.4

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.
@@ -0,0 +1,59 @@
1
+ name: Deploy
2
+
3
+ on:
4
+ push:
5
+ tags: ['v*']
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ deploy:
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - name: Checkout code
14
+ uses: actions/checkout@v4
15
+
16
+ - name: Setup Node.js
17
+ uses: actions/setup-node@v4
18
+ with:
19
+ node-version: '22'
20
+ cache: 'yarn'
21
+
22
+ - name: Install dependencies
23
+ run: yarn install --frozen-lockfile
24
+
25
+ - name: Build docs site
26
+ run: yarn docs:build
27
+
28
+ - name: Package build
29
+ run: tar -czf deploy.tar.gz -C build .
30
+
31
+ - name: Upload to VPS
32
+ uses: appleboy/scp-action@v0.1.7
33
+ with:
34
+ host: ${{ vars.VPS_HOST }}
35
+ username: ${{ vars.VPS_USER }}
36
+ port: ${{ vars.VPS_PORT || 22 }}
37
+ key: ${{ secrets.VPS_SSH_KEY }}
38
+ source: deploy.tar.gz
39
+ target: /tmp
40
+
41
+ - name: Deploy on VPS
42
+ uses: appleboy/ssh-action@v1.2.0
43
+ env:
44
+ DEPLOY_PATH: ${{ vars.VPS_DEPLOY_PATH }}
45
+ with:
46
+ host: ${{ vars.VPS_HOST }}
47
+ username: ${{ vars.VPS_USER }}
48
+ port: ${{ vars.VPS_PORT || 22 }}
49
+ key: ${{ secrets.VPS_SSH_KEY }}
50
+ envs: DEPLOY_PATH
51
+ script: |
52
+ set -e
53
+ # /var/www is root-owned; ci needs sudo to create the deploy path
54
+ sudo mkdir -p "$DEPLOY_PATH"
55
+ sudo chown "$USER:$USER" "$DEPLOY_PATH"
56
+ TMP_DIR=$(mktemp -d)
57
+ tar -xzf /tmp/deploy.tar.gz -C "$TMP_DIR"
58
+ rsync -a --delete "$TMP_DIR"/ "$DEPLOY_PATH"/
59
+ rm -rf "$TMP_DIR" /tmp/deploy.tar.gz
@@ -50,7 +50,6 @@ function VideoItem({ src, size, isActive, }) {
50
50
  function Item({ src, kind, size, isActive, }) {
51
51
  const [loaded, setLoaded] = useState(false);
52
52
  const [isError, setIsError] = useState(false);
53
- const style = {};
54
53
  const imgRef = useRef(null);
55
54
  useLayoutEffect(() => {
56
55
  if (kind === 'video')
@@ -92,10 +91,7 @@ function Item({ src, kind, size, isActive, }) {
92
91
  if (kind === 'video') {
93
92
  return jsx(VideoItem, { src: src, size: size, isActive: isActive });
94
93
  }
95
- if (loaded)
96
- style.backgroundImage = `url(${src})`;
97
- return (jsx("div", { className: S.item, style: style, children: !loaded &&
98
- (isError ? (jsx(Icon, { type: "brokenImage", className: S.brokenImage })) : (jsxs(Fragment, { children: [jsx("img", { ref: imgRef, src: src, onLoad: () => setLoaded(true), onError: () => setIsError(true) }), jsx(Spinner, { size: size })] }))) }));
94
+ return (jsx("div", { className: S.item, children: isError ? (jsx(Icon, { type: "brokenImage", className: S.brokenImage })) : (jsxs(Fragment, { children: [jsx("img", { ref: imgRef, src: src, alt: "", className: cn(S.image, loaded && S.imageLoaded), draggable: false, onLoad: () => setLoaded(true), onError: () => setIsError(true) }), !loaded && jsx(Spinner, { size: size })] })) }));
99
95
  }
100
96
  class Gallery extends Component {
101
97
  store;
@@ -1,7 +1,7 @@
1
1
  import styleInject from '../../../node_modules/style-inject/dist/style-inject.es.js';
2
2
 
3
- var css_248z = ".Gallery_item__P4qTJ,.Gallery_root__-Crit{height:100%;width:100%}.Gallery_root__-Crit{overflow:hidden;position:relative}.Gallery_inner__4FAPt{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:flex;height:100%;position:absolute;touch-action:none;transform:translate3d(-33.33333%,0,0);width:calc(300% + 1px)}.Gallery_single__Wfd9h .Gallery_inner__4FAPt{transform:none;width:100%}.Gallery_single__Wfd9h .Gallery_item__P4qTJ{width:100%}.Gallery_inner__4FAPt.Gallery_left__zrrmv,.Gallery_inner__4FAPt.Gallery_right__dpZ-m{transition:transform 0s ease-out;transition-duration:.2s}.Gallery_inner__4FAPt.Gallery_left__zrrmv{transform:translateZ(0)!important}.Gallery_inner__4FAPt.Gallery_right__dpZ-m{transform:translate3d(-66.66667%,0,0)!important}.Gallery_inner__4FAPt.Gallery_initialBounce__nZnKd{animation:Gallery_bounce__buqva 1s ease-out}.Gallery_item__P4qTJ{align-items:center;background-position:50%;background-repeat:no-repeat;background-size:contain;display:flex;justify-content:center;width:33.33333%}.Gallery_cover__ZGx5X .Gallery_item__P4qTJ{background-size:cover}.Gallery_item__P4qTJ>img{opacity:0;pointer-events:none;position:absolute}.Gallery_brokenImage__Bj3O-{height:50%;opacity:.2;width:50%}.Gallery_videoItem__06r39 .Gallery_video__vKK23{max-height:100%;max-width:100%}.Gallery_arr__knicI{background:transparent!important;height:100%;min-height:100%;opacity:0;padding:10%;position:absolute;top:0;transition:opacity .1s ease-out;z-index:1}.Gallery_arr__knicI.Gallery_left__zrrmv{justify-content:flex-start;left:0}.Gallery_arr__knicI.Gallery_right__dpZ-m{justify-content:flex-end;right:0;width:77%}.Gallery_arr__knicI:hover{opacity:1}@keyframes Gallery_bounce__buqva{0%{left:0}50%{left:-20%}80%{left:10%}to{left:0}}";
4
- var S = {"root":"Gallery_root__-Crit","item":"Gallery_item__P4qTJ","inner":"Gallery_inner__4FAPt","single":"Gallery_single__Wfd9h","left":"Gallery_left__zrrmv","right":"Gallery_right__dpZ-m","initialBounce":"Gallery_initialBounce__nZnKd","bounce":"Gallery_bounce__buqva","cover":"Gallery_cover__ZGx5X","brokenImage":"Gallery_brokenImage__Bj3O-","videoItem":"Gallery_videoItem__06r39","video":"Gallery_video__vKK23","arr":"Gallery_arr__knicI"};
3
+ var css_248z = ".Gallery_item__P4qTJ,.Gallery_root__-Crit{height:100%;width:100%}.Gallery_root__-Crit{overflow:hidden;position:relative}.Gallery_inner__4FAPt{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:flex;height:100%;position:absolute;touch-action:none;transform:translate3d(-33.33333%,0,0);width:calc(300% + 1px)}.Gallery_single__Wfd9h .Gallery_inner__4FAPt{transform:none;width:100%}.Gallery_single__Wfd9h .Gallery_item__P4qTJ{width:100%}.Gallery_inner__4FAPt.Gallery_left__zrrmv,.Gallery_inner__4FAPt.Gallery_right__dpZ-m{transition:transform 0s ease-out;transition-duration:.2s}.Gallery_inner__4FAPt.Gallery_left__zrrmv{transform:translateZ(0)!important}.Gallery_inner__4FAPt.Gallery_right__dpZ-m{transform:translate3d(-66.66667%,0,0)!important}.Gallery_inner__4FAPt.Gallery_initialBounce__nZnKd{animation:Gallery_bounce__buqva 1s ease-out}.Gallery_item__P4qTJ{align-items:center;display:flex;justify-content:center;position:relative;width:33.33333%}.Gallery_image__FkvmG{height:auto;max-height:100%;max-width:100%;-o-object-fit:contain;object-fit:contain;opacity:0;transition:opacity .15s ease-out;width:auto}.Gallery_image__FkvmG.Gallery_imageLoaded__1rGwn{opacity:1}.Gallery_cover__ZGx5X .Gallery_image__FkvmG{height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.Gallery_brokenImage__Bj3O-{height:50%;opacity:.2;width:50%}.Gallery_videoItem__06r39 .Gallery_video__vKK23{max-height:100%;max-width:100%}.Gallery_arr__knicI{background:transparent!important;height:100%;min-height:100%;opacity:0;padding:10%;position:absolute;top:0;transition:opacity .1s ease-out;z-index:1}.Gallery_arr__knicI.Gallery_left__zrrmv{justify-content:flex-start;left:0}.Gallery_arr__knicI.Gallery_right__dpZ-m{justify-content:flex-end;right:0;width:77%}.Gallery_arr__knicI:hover{opacity:1}@keyframes Gallery_bounce__buqva{0%{left:0}50%{left:-20%}80%{left:10%}to{left:0}}";
4
+ var S = {"root":"Gallery_root__-Crit","item":"Gallery_item__P4qTJ","inner":"Gallery_inner__4FAPt","single":"Gallery_single__Wfd9h","left":"Gallery_left__zrrmv","right":"Gallery_right__dpZ-m","initialBounce":"Gallery_initialBounce__nZnKd","bounce":"Gallery_bounce__buqva","image":"Gallery_image__FkvmG","imageLoaded":"Gallery_imageLoaded__1rGwn","cover":"Gallery_cover__ZGx5X","brokenImage":"Gallery_brokenImage__Bj3O-","videoItem":"Gallery_videoItem__06r39","video":"Gallery_video__vKK23","arr":"Gallery_arr__knicI"};
5
5
  styleInject(css_248z);
6
6
 
7
7
  export { S as default };
@@ -129,6 +129,11 @@ class Popup extends Component {
129
129
  vv.removeEventListener('resize', this.onBoundaryGeometryChange);
130
130
  vv.removeEventListener('scroll', this.onBoundaryGeometryChange);
131
131
  }
132
+ // These are registered in componentDidMount; omitting removal left orphaned
133
+ // capture listeners that kept calling close/onClose after portal remounts.
134
+ document.removeEventListener('pointerdown', this.onDocPointerDown, true);
135
+ document.removeEventListener('pointerup', this.onDocPointerUp, true);
136
+ document.removeEventListener('keydown', this.onDocKeyDown, true);
132
137
  document.removeEventListener('keyup', this.onDocKeyUp);
133
138
  if (this.scrollParent) {
134
139
  this.scrollParent.removeEventListener('scroll', this.close);
@@ -30,6 +30,7 @@ function Select2(props) {
30
30
  const contentRef = useRef(null);
31
31
  const scrollInnerRef = useRef(null);
32
32
  const pointerPressedInside = useRef(false);
33
+ const pressStartedInside = useRef(false);
33
34
  const pointerPressTimer = useRef(0);
34
35
  const blurTimer = useRef(0);
35
36
  const [labelClipPath, setLabelClipPath] = useState('');
@@ -161,19 +162,39 @@ function Select2(props) {
161
162
  else
162
163
  open();
163
164
  };
165
+ const markPressInside = (isInside) => {
166
+ window.clearTimeout(pointerPressTimer.current);
167
+ pointerPressedInside.current = isInside;
168
+ pointerPressTimer.current = window.setTimeout(() => (pointerPressedInside.current = false), POINTER_PRESS_TTL);
169
+ };
164
170
  useEvent({
165
171
  event: 'pointerdown',
166
172
  isCapture: true,
167
173
  callback: e => {
168
- window.clearTimeout(pointerPressTimer.current);
169
- pointerPressedInside.current = isInsideSelect(e.target);
170
- pointerPressTimer.current = window.setTimeout(() => (pointerPressedInside.current = false), POINTER_PRESS_TTL);
174
+ pressStartedInside.current = isInsideSelect(e.target);
175
+ markPressInside(pressStartedInside.current);
176
+ },
177
+ });
178
+ useEvent({
179
+ event: 'pointerup',
180
+ isCapture: true,
181
+ callback: () => {
182
+ // The release can land on the portalled popup that mounted under the
183
+ // cursor mid-gesture, so the up-target is not a reliable inside signal.
184
+ if (pressStartedInside.current)
185
+ markPressInside(true);
186
+ pressStartedInside.current = false;
171
187
  },
172
188
  });
173
189
  useEvent({
174
190
  event: 'click',
175
191
  isActive: isOpen,
176
192
  callback: e => {
193
+ // The click concluding a press that started inside must not count as an
194
+ // outside click: the portalled popup can mount under the cursor, which
195
+ // retargets the click to a common ancestor outside the select.
196
+ if (pointerPressedInside.current)
197
+ return;
177
198
  if (!isInsideSelect(e.target))
178
199
  close();
179
200
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homecode/ui",
3
- "version": "5.7.0",
3
+ "version": "5.7.4",
4
4
  "description": "React UI components library",
5
5
  "scripts": {
6
6
  "tests": "jest",