@ainias42/react-bootstrap-mobile 0.2.12 → 0.2.13

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,4 +1,5 @@
1
1
  import * as React from 'react';
2
+ import { ColorResult } from '@uiw/react-color';
2
3
  import { OptionalListener } from '../../Hooks/useListener';
3
4
  export type ColorInputProps<OnChangeData> = {
4
5
  defaultValue?: string;
@@ -6,7 +7,6 @@ export type ColorInputProps<OnChangeData> = {
6
7
  label?: string;
7
8
  onChangeColor?: (newColor: string) => void;
8
9
  onOpen?: (currentColor: string) => void;
9
- onChangeColorComplete?: (newColor: string) => void;
10
10
  onClose?: (newColor: string) => void;
11
11
  disableAlpha?: boolean;
12
12
  presetColors?: string[];
@@ -14,7 +14,7 @@ export type ColorInputProps<OnChangeData> = {
14
14
  disabled?: boolean;
15
15
  error?: string;
16
16
  className?: string;
17
- } & OptionalListener<'onChange', OnChangeData>;
18
- declare function ColorInput<OnChangeData>({ defaultValue, value, label, onChangeColor, onChangeColorComplete, onOpen, onClose, disableAlpha, presetColors, error, sharedColorKey, disabled, className, ...otherProps }: ColorInputProps<OnChangeData>): React.JSX.Element;
17
+ } & OptionalListener<'onChange', OnChangeData, ColorResult>;
18
+ declare function ColorInput<OnChangeData>({ defaultValue, value, label, onChangeColor, onOpen, onClose, disableAlpha, presetColors, error, sharedColorKey, disabled, className, ...otherProps }: ColorInputProps<OnChangeData>): React.JSX.Element;
19
19
  declare const ColorInputMemo: typeof ColorInput;
20
20
  export { ColorInputMemo as ColorInput };
@@ -1,4 +1,4 @@
1
- export declare function useSharedSelectedColor(key?: string, numberSavedColors?: number): {
1
+ export declare function useSharedSelectedColor(key: string | undefined, predefinedColors?: string[], numberSavedColors?: number): {
2
2
  colors: string[];
3
3
  addColor: (newColor: string) => void;
4
4
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainias42/react-bootstrap-mobile",
3
- "version": "0.2.12",
3
+ "version": "0.2.13",
4
4
  "description": "Mobile React Components using Bootstrap",
5
5
  "main": "dist/bootstrapReactMobile",
6
6
  "scripts": {
@@ -54,7 +54,6 @@
54
54
  "@fortawesome/react-fontawesome": "^0.2.2",
55
55
  "@types/react": ">=18.0.0",
56
56
  "@types/react-beautiful-dnd": "^13.1.8",
57
- "@types/react-color": "^3.0.12",
58
57
  "@types/react-dom": ">=18.0.0",
59
58
  "@types/react-table": "^7.7.20",
60
59
  "@types/react-window": "^1.8.8",
@@ -95,6 +94,7 @@
95
94
  "dependencies": {
96
95
  "@ainias42/js-helper": ">=0.8.16",
97
96
  "@types/react-virtualized-auto-sizer": "^1.0.4",
97
+ "@uiw/react-color": "^2.5.5",
98
98
  "classnames": "^2.5.1",
99
99
  "isomorphic-style-loader": "^5.3.2",
100
100
  "react-color": "^2.19.3",
@@ -11,7 +11,7 @@ import {
11
11
  useEffect,
12
12
  MouseEvent,
13
13
  PointerEvent,
14
- useRef, DragEventHandler
14
+ useRef
15
15
  } from 'react';
16
16
  import {withForwardRef} from '../../helper/withForwardRef';
17
17
  import {useComposedRef} from "../Hooks/useComposedRef";
@@ -4,12 +4,10 @@ import { withMemo } from '../../helper/withMemo';
4
4
  import { Block } from '../Layout/Block';
5
5
  import { Text, TEXT_SIZE } from '../Text/Text';
6
6
  import { Clickable } from '../Clickable/Clickable';
7
-
8
7
  import styles from './buttonDialog.scss';
9
8
  import { RbmComponentProps, WithNoChildren } from '../RbmComponentProps';
10
9
  import classNames from 'classnames';
11
10
  import { Flavor } from "../Flavor";
12
- import { Size } from "../../Size";
13
11
 
14
12
  export type ButtonDialogProps = RbmComponentProps<
15
13
  {
@@ -40,7 +40,7 @@ export const DialogBackground = withMemo(function DialogBackground({
40
40
  <Block __allowChildren="all" className={classNames(styles.dialogBackground, className)} style={style}>
41
41
  {(!!title || !!onClose) && <Flex horizontal={true} className={styles.title}>{!!title &&
42
42
  <Grow><Heading >{title}</Heading></Grow>}{!!onClose &&
43
- <Clickable onClick={onClose}><Icon size={"lg"} icon={faCircleXmark}/></Clickable>}</Flex>}
43
+ <Clickable onClick={onClose}><Icon size="lg" icon={faCircleXmark}/></Clickable>}</Flex>}
44
44
  {children}
45
45
  </Block>
46
46
  );
@@ -14,7 +14,7 @@ export type ShowDialog = <
14
14
 
15
15
  const DialogContext = React.createContext<ShowDialog>(() => {
16
16
  console.error("DialogContext not initialized");
17
- return Promise.reject("DialogContext not initialized")
17
+ return Promise.reject(new Error("DialogContext not initialized"));
18
18
  });
19
19
  export const DialogProvider = DialogContext.Provider;
20
20
 
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
- import { useCallback, useRef, useState, MouseEvent } from 'react';
3
- import { Color, ColorChangeHandler, ColorResult, SketchPicker } from 'react-color';
2
+ import { useCallback, useRef, useState, MouseEvent, useMemo } from 'react';
3
+ import { ColorResult, Sketch, SwatchPresetColor } from '@uiw/react-color';
4
4
  import { OptionalListener, useListener } from '../../Hooks/useListener';
5
5
  import { withMemo } from '../../../helper/withMemo';
6
6
  import styles from './colorInput.scss';
@@ -16,7 +16,6 @@ export type ColorInputProps<OnChangeData> = {
16
16
  label?: string;
17
17
  onChangeColor?: (newColor: string) => void;
18
18
  onOpen?: (currentColor: string) => void;
19
- onChangeColorComplete?: (newColor: string) => void;
20
19
  onClose?: (newColor: string) => void;
21
20
  disableAlpha?: boolean;
22
21
  presetColors?: string[];
@@ -24,26 +23,13 @@ export type ColorInputProps<OnChangeData> = {
24
23
  disabled?: boolean
25
24
  error?: string;
26
25
  className?: string;
27
- } & OptionalListener<'onChange', OnChangeData>;
28
-
29
- function convertToHex(color: { r: number; g: number; b: number; a?: number }, disableAlpha?: boolean) {
30
- let newColor = `#${color.r.toString(16).padStart(2, '0')}${color.g.toString(16).padStart(2, '0')}${color.b
31
- .toString(16)
32
- .padStart(2, '0')}`;
33
- if (color.a !== undefined && !disableAlpha) {
34
- newColor += Math.round(color.a * 255)
35
- .toString(16)
36
- .padStart(2, '0');
37
- }
38
- return newColor;
39
- }
26
+ } & OptionalListener<'onChange', OnChangeData, ColorResult>;
40
27
 
41
28
  function ColorInput<OnChangeData>({
42
29
  defaultValue,
43
30
  value,
44
31
  label,
45
32
  onChangeColor,
46
- onChangeColorComplete,
47
33
  onOpen,
48
34
  onClose,
49
35
  disableAlpha,
@@ -65,34 +51,34 @@ function ColorInput<OnChangeData>({
65
51
  const [isOpen, setIsOpen] = useState(false);
66
52
  const [position, setPosition] = useState({x: 0, y: 0});
67
53
 
68
- const {colors, addColor} = useSharedSelectedColor(sharedColorKey);
54
+ const {colors, addColor} = useSharedSelectedColor(sharedColorKey, presetColors);
69
55
  const realIsOpen = disabled !== true && isOpen;
70
56
 
71
- const colVal: Color = value ?? color;
57
+ const colVal = useMemo(() => {
58
+ const newVal = value ?? color;
59
+ if (disableAlpha && newVal.length === 9) {
60
+ return newVal.substring(0, 7);
61
+ }
62
+ if (disableAlpha && newVal.length === 5) {
63
+ return newVal.substring(0,4);
64
+ }
65
+ return newVal;
66
+ }, [value, color, disableAlpha]);
67
+
72
68
  // Selectors
73
69
 
74
70
  // Callbacks
75
- const onChangeWithData = useListener<'onChange', OnChangeData>('onChange', otherProps);
76
- const onChange = useCallback<ColorChangeHandler>(
77
- (newColor: ColorResult, e) => {
78
- const hexColor = convertToHex(newColor.rgb, disableAlpha);
71
+ const onChangeWithData = useListener<'onChange', OnChangeData, ColorResult>('onChange', otherProps);
72
+ const onChange = useCallback(
73
+ (newColor: ColorResult) => {
74
+ const hexColor = newColor.hexa;
79
75
  setColor(hexColor);
80
76
  if (onChangeColor) {
81
77
  onChangeColor(hexColor);
82
78
  }
83
- onChangeWithData(e);
84
- },
85
- [disableAlpha, onChangeColor, onChangeWithData]
86
- );
87
- const onChangeComplete = useCallback(
88
- (newColor: ColorResult) => {
89
- const hexColor = convertToHex(newColor.rgb, disableAlpha);
90
- setColor(hexColor);
91
- if (onChangeColorComplete) {
92
- onChangeColorComplete(hexColor);
93
- }
79
+ onChangeWithData(newColor);
94
80
  },
95
- [disableAlpha, onChangeColorComplete]
81
+ [onChangeColor, onChangeWithData]
96
82
  );
97
83
 
98
84
  const onMenuClose = useCallback(
@@ -141,10 +127,9 @@ function ColorInput<OnChangeData>({
141
127
  <>
142
128
  <span className={classNames(styles.colorInput, className)}>
143
129
  <Menu x={position.x} y={position.y} isOpen={realIsOpen} onClose={onMenuClose}>
144
- <SketchPicker
130
+ <Sketch
145
131
  color={colVal}
146
132
  onChange={onChange}
147
- onChangeComplete={onChangeComplete}
148
133
  disableAlpha={disableAlpha}
149
134
  presetColors={presetColors ?? colors}
150
135
  />
@@ -7,6 +7,22 @@
7
7
  height: 1rem;
8
8
  display: inline-block;
9
9
  border: 1px solid black;
10
+ position: relative;
11
+
12
+ &:before {
13
+ content: '';
14
+ position: absolute;
15
+ top: 0;
16
+ left: 0;
17
+ right: 0;
18
+ bottom: 0;
19
+ display: block;
20
+ width: 100%;
21
+ height: 100%;
22
+ z-index: -1;
23
+ background: repeating-conic-gradient(#cccccc 0% 25%, #ffffff 0% 50%);
24
+ }
25
+
10
26
  }
11
27
 
12
28
  .modalContainer {
@@ -31,3 +47,26 @@
31
47
  margin-right: 0.2rem;
32
48
  }
33
49
  }
50
+
51
+
52
+ :global(.w-color-swatch) {
53
+ z-index: 0;
54
+
55
+ > div {
56
+ position: relative;
57
+
58
+ &:before {
59
+ content: '';
60
+ position: absolute;
61
+ top: 0;
62
+ left: 0;
63
+ right: 0;
64
+ bottom: 0;
65
+ display: block;
66
+ width: 100%;
67
+ height: 100%;
68
+ z-index: -1;
69
+ background: repeating-conic-gradient(#cccccc 0% 25%, #ffffff 0% 50%);
70
+ }
71
+ }
72
+ }
@@ -1,9 +1,14 @@
1
- import { useCallback, useMemo, useRef, useState } from 'react';
1
+ import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
2
2
  import { Random } from '@ainias42/js-helper';
3
3
 
4
4
  const sharedSelectedColor: Record<string, { colors: string[]; updateFunctions: (() => void)[] }> = {};
5
5
 
6
- export function useSharedSelectedColor(key?: string, numberSavedColors = 15) {
6
+ function localStorageKey (key: string) {
7
+ return `sharedSelectedColor-${key}`;
8
+ };
9
+
10
+ export function useSharedSelectedColor(key: string|undefined, predefinedColors: string[] = [], numberSavedColors = 16) {
11
+ const shouldSaveToLocalStorage = typeof window !== 'undefined' && window.localStorage !== undefined && !!key;
7
12
  const [, setVersion] = useState(1);
8
13
  const innerKey = useRef(Random.getStringRandom(12));
9
14
  const realKey = key ?? innerKey.current;
@@ -22,6 +27,10 @@ export function useSharedSelectedColor(key?: string, numberSavedColors = 15) {
22
27
 
23
28
  const addColor = useCallback(
24
29
  (newColor: string) => {
30
+ if (predefinedColors.includes(newColor)) {
31
+ return;
32
+ }
33
+
25
34
  sharedSelectedColor[realKey].colors = sharedSelectedColor[realKey].colors.filter(
26
35
  (color) => color !== newColor
27
36
  );
@@ -29,12 +38,32 @@ export function useSharedSelectedColor(key?: string, numberSavedColors = 15) {
29
38
  if (sharedSelectedColor[realKey].colors.length > numberSavedColors) {
30
39
  sharedSelectedColor[realKey].colors.splice(numberSavedColors, 1);
31
40
  }
41
+ if (shouldSaveToLocalStorage){
42
+ localStorage.setItem(localStorageKey(realKey), JSON.stringify(sharedSelectedColor[realKey].colors));
43
+ }
32
44
 
33
45
  // triggers rerender
34
46
  sharedSelectedColor[realKey].updateFunctions.forEach((u) => u());
35
47
  },
36
- [numberSavedColors, realKey]
48
+ [numberSavedColors, realKey, shouldSaveToLocalStorage]
37
49
  );
38
50
 
39
- return { colors: sharedSelectedColor[realKey]?.colors, addColor };
51
+ useLayoutEffect(() => {
52
+ if (shouldSaveToLocalStorage){
53
+ const savedColors = localStorage.getItem(localStorageKey(realKey));
54
+ if (savedColors) {
55
+ sharedSelectedColor[realKey].colors = JSON.parse(savedColors);
56
+ setVersion((old) => old + 1);
57
+ }
58
+ }
59
+ }, [realKey, shouldSaveToLocalStorage]);
60
+
61
+ const realColors = useMemo(() => {
62
+ if (predefinedColors.length > 0) {
63
+ return [...predefinedColors, ...sharedSelectedColor[realKey].colors.filter(color => !predefinedColors.includes(color))].slice(0, numberSavedColors);
64
+ }
65
+ return sharedSelectedColor[realKey].colors;
66
+ }, [numberSavedColors, predefinedColors, realKey]);
67
+
68
+ return { colors: realColors, addColor };
40
69
  }
@@ -33,8 +33,8 @@ export const FileInputController = withMemo(function FileInputController<Values
33
33
  const setErrorMessage = useCallback((error: string) => {
34
34
  setError(name, {
35
35
  message: error,
36
- })
37
- }, []);
36
+ });
37
+ }, [name, setError]);
38
38
 
39
39
  return (
40
40
  <FileInput
@@ -35,7 +35,7 @@ export const HookForm = withMemo(function HookForm<TFieldValues extends FieldVal
35
35
 
36
36
  return <FormProvider {...methods}>
37
37
  <SendFormContext.Provider value={innerOnSend}>
38
- <LoadingArea loading={methods.formState.isSubmitting} __allowChildren={"all"}>
38
+ <LoadingArea loading={methods.formState.isSubmitting} __allowChildren="all">
39
39
  {children}
40
40
  </LoadingArea>
41
41
  </SendFormContext.Provider>
@@ -25,5 +25,5 @@ export const FormError = withMemo(function FormError({error}: FormErrorProps) {
25
25
  return null;
26
26
  }
27
27
 
28
- return <Block className={styles.error}><Text>{error}</Text></Block>
28
+ return <Block className={styles.error}><Text>{error}</Text></Block>;
29
29
  }, styles);
@@ -16,7 +16,6 @@ import { Image } from '../../../Image/Image';
16
16
  import { Clickable } from '../../../Clickable/Clickable';
17
17
  import { Inline } from '../../../Layout/Inline';
18
18
  import { FileType } from "./FileType";
19
- import { InlineBlock } from "../../../Layout/InlineBlock";
20
19
  import { FormError } from "../../FormError";
21
20
 
22
21
 
@@ -67,7 +67,7 @@ export const Select = withMemo(function Select<OnChangeData>({
67
67
  }
68
68
  onChangeWithData(e);
69
69
  },
70
- [onChangeWithData, onChangeValue]
70
+ [onChangeWithData, onChangeValue, useNumericValues]
71
71
  );
72
72
 
73
73
  // Effects
@@ -53,7 +53,7 @@ export const FullScreen = withMemo(function FullScreen<AsTag extends keyof JSX.I
53
53
  } else {
54
54
  containerRef.current?.requestFullscreen();
55
55
  }
56
- }, [onEnterFullscreen, onLeaveFullscreen]);
56
+ }, []);
57
57
 
58
58
  // Effects
59
59
  useEffect(() => {
@@ -71,28 +71,26 @@ export const FullScreen = withMemo(function FullScreen<AsTag extends keyof JSX.I
71
71
 
72
72
  useEffect(() => {
73
73
  if (!containerRef.current) {
74
- return;
74
+ return undefined;
75
75
  }
76
76
 
77
77
  const container = containerRef.current;
78
78
  const listener = () => {
79
- // @ts-ignore
79
+ // @ts-expect-error the typing is not completely correct
80
80
  const fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement;
81
81
  if (fullscreenElement === container) {
82
- console.log("LOG-d enter fullscreen")
83
82
  onEnterFullscreen?.();
84
83
  } else {
85
- console.log("LOG-d leave fullscreen")
86
84
  onLeaveFullscreen?.();
87
85
  }
88
- }
86
+ };
89
87
  container.addEventListener('fullscreenchange', listener);
90
88
  container.addEventListener('webkitfullscreenchange', listener);
91
89
 
92
90
  return () => {
93
91
  container.removeEventListener('fullscreenchange', listener);
94
92
  container.removeEventListener('webkitfullscreenchange', listener);
95
- }
93
+ };
96
94
  }, [onEnterFullscreen, onLeaveFullscreen]);
97
95
 
98
96
  // Other
@@ -1,4 +1,4 @@
1
- import { ForwardedRef, useCallback, useEffect, useRef } from 'react';
1
+ import { ForwardedRef, useCallback } from 'react';
2
2
 
3
3
  export function useComposedRef<RefVal>(...refs: (ForwardedRef<RefVal> | undefined)[]) {
4
4
  return useCallback((val: RefVal | null) => {
@@ -3,12 +3,13 @@ import { useEffect } from "react";
3
3
  export function useDelayedEffect(effect: () => void|(() => void), dependencies: any[], delay = 100){
4
4
  useEffect(() => {
5
5
  let cleanup: (() => void)|void | undefined;
6
- let timeout = setTimeout(() => {
6
+ const timeout = setTimeout(() => {
7
7
  cleanup = effect();
8
8
  }, delay);
9
9
  return () => {
10
10
  clearTimeout(timeout);
11
- cleanup?.()
11
+ cleanup?.();
12
12
  };
13
- }, dependencies);
13
+ // eslint-disable-next-line react-hooks/exhaustive-deps
14
+ }, [delay, ...dependencies]);
14
15
  }
@@ -15,7 +15,7 @@ export function useRerender(defaultDelay = 0){
15
15
  updateRenderCounter(old => old + 1);
16
16
  }, delay);
17
17
  }
18
- }, [])
18
+ }, [defaultDelay]);
19
19
 
20
20
  return [update, renderCounter] as const;
21
21
  }
@@ -1,6 +1,5 @@
1
- import React, { CSSProperties, ReactElement, ReactNode, useCallback, useState } from 'react';
1
+ import React, { useCallback, useState } from 'react';
2
2
  import InfiniteLoader from "react-window-infinite-loader";
3
- import { RbmComponentProps } from "../RbmComponentProps";
4
3
  import { List, ListProps } from "./List";
5
4
  import { withMemo } from "../../helper/withMemo";
6
5
 
@@ -34,12 +33,12 @@ export const InfiniteList = withMemo(function InfiniteList<ItemType>({
34
33
  if (!isPageLoading) {
35
34
  setIsPageLoading(true);
36
35
  try {
37
- loadNextPage()
36
+ loadNextPage();
38
37
  } finally {
39
38
  setIsPageLoading(false);
40
39
  }
41
40
  }
42
- }, [isPageLoading, loadNextPage])
41
+ }, [isPageLoading, loadNextPage]);
43
42
 
44
43
  // Effects
45
44
 
@@ -1,9 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { ComponentType, CSSProperties, ForwardedRef, ReactElement, ReactNode, useCallback, useState } from 'react';
3
3
  import { RbmComponentProps } from '../RbmComponentProps';
4
-
5
4
  import styles from './list.scss';
6
- import { withMemo } from '../../helper/withMemo';
7
5
  import { FixedSizeList, FixedSizeListProps, ListChildComponentProps } from 'react-window';
8
6
  import AutoSizer from 'react-virtualized-auto-sizer';
9
7
  import { SizeCalculator, SizeCalculatorProps } from '../SizeCalculator/SizeCalculator';
@@ -1,19 +1,21 @@
1
1
  @import "designMixin";
2
2
 
3
- * {
4
- box-sizing: border-box;
5
- -webkit-font-smoothing: antialiased;
6
- font-weight: 400;
7
- }
8
-
9
- .#{$material} {
3
+ @layer rbm {
10
4
  * {
11
- font-family: "Roboto", "Noto", sans-serif;
5
+ box-sizing: border-box;
6
+ -webkit-font-smoothing: antialiased;
7
+ font-weight: 400;
12
8
  }
13
- }
14
9
 
15
- .#{$flat} {
16
- * {
17
- font-family: -apple-system, "Helvetica Neue", "Helvetica", "Arial", "Lucida Grande", sans-serif;
10
+ .#{$material} {
11
+ * {
12
+ font-family: "Roboto", "Noto", sans-serif;
13
+ }
14
+ }
15
+
16
+ .#{$flat} {
17
+ * {
18
+ font-family: -apple-system, "Helvetica Neue", "Helvetica", "Arial", "Lucida Grande", sans-serif;
19
+ }
18
20
  }
19
21
  }