@ainias42/react-bootstrap-mobile 0.1.31 → 0.2.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.
Files changed (52) hide show
  1. package/.eslintrc.json +1 -1
  2. package/bin/updateCopies.js +5 -1
  3. package/bootstrapReactMobile.ts +2 -0
  4. package/dist/bootstrapReactMobile.d.ts +2 -0
  5. package/dist/bootstrapReactMobile.js +1611 -1070
  6. package/dist/bootstrapReactMobile.js.map +1 -1
  7. package/dist/src/Components/DragAndDrop/DropArea.d.ts +1 -3
  8. package/dist/src/Components/Hooks/useClientLayoutEffect.d.ts +2 -0
  9. package/dist/src/Components/Hooks/useDelayed.d.ts +1 -1
  10. package/dist/src/Components/Layout/Block.d.ts +1 -1
  11. package/dist/src/Components/Layout/Flex.d.ts +1 -1
  12. package/dist/src/Components/Layout/Inline.d.ts +1 -1
  13. package/dist/src/Components/Layout/InlineBlock.d.ts +1 -1
  14. package/dist/src/Components/Layout/View.d.ts +2 -3
  15. package/dist/src/Components/Layout/ViewWithoutListeners.d.ts +2 -3
  16. package/dist/src/Components/Toast/ToastContext.d.ts +11 -0
  17. package/package.json +64 -53
  18. package/react-bootstrap-mobile.scss +2 -2
  19. package/src/Components/Card/Card.tsx +0 -1
  20. package/src/Components/Dialog/DialogContainer.tsx +15 -13
  21. package/src/Components/Dialog/DialogContext.ts +4 -1
  22. package/src/Components/DragAndDrop/DropArea.tsx +2 -6
  23. package/src/Components/FormElements/Button/Button.tsx +1 -1
  24. package/src/Components/FormElements/ColorInput/ColorInput.tsx +3 -2
  25. package/src/Components/FormElements/Input/FileInput/FileInput.tsx +1 -1
  26. package/src/Components/FormElements/Input/FileInput/MultipleFileInput.tsx +1 -3
  27. package/src/Components/FormElements/Input/HiddenInput.tsx +0 -1
  28. package/src/Components/FormElements/Input/Input.tsx +30 -20
  29. package/src/Components/FormElements/Select/Select.tsx +1 -1
  30. package/src/Components/FullScreen/FullScreen.tsx +1 -1
  31. package/src/Components/Hooks/useClientLayoutEffect.ts +8 -0
  32. package/src/Components/Hooks/useDelayed.ts +1 -1
  33. package/src/Components/Hooks/useMousePosition.ts +3 -2
  34. package/src/Components/Layout/Grid/GridItem.tsx +0 -1
  35. package/src/Components/Layout/Grow.tsx +2 -4
  36. package/src/Components/Layout/View.tsx +5 -10
  37. package/src/Components/Layout/ViewWithoutListeners.tsx +4 -9
  38. package/src/Components/Menu/Menu.tsx +9 -9
  39. package/src/Components/RbmComponentProps.ts +0 -1
  40. package/src/Components/SpoilerList/Spoiler/Spoiler.tsx +1 -3
  41. package/src/Components/Toast/Toast.tsx +0 -1
  42. package/src/Components/Toast/ToastContainer.tsx +59 -3
  43. package/src/Components/Toast/ToastContext.ts +9 -0
  44. package/src/Components/TopBar/TopBarButton.tsx +2 -4
  45. package/src/Components/TopBar/topBar.scss +4 -0
  46. package/src/helper/withRenderBrowserOnly.tsx +2 -2
  47. package/src/scss/_baseClasses.scss +6 -6
  48. package/src/scss/_default.scss +2 -0
  49. package/src/scss/_variables.scss +2 -2
  50. package/webpack.config.js +2 -1
  51. package/src/scss/_animations.scss +0 -46
  52. package/src/scss/_mobileMixin.scss +0 -35
@@ -77,5 +77,5 @@ export const FullScreen = withMemo(function FullScreen<AsTag extends keyof JSX.I
77
77
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
78
78
  // @ts-ignore
79
79
  return React.createElement(element, props, children);
80
- })
80
+ });
81
81
 
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+
3
+ export function useClientLayoutEffect(...params: Parameters<typeof React.useLayoutEffect>) {
4
+ if (typeof window !== 'undefined') {
5
+ // eslint-disable-next-line react-hooks/exhaustive-deps,react-hooks/rules-of-hooks
6
+ React.useLayoutEffect(...params);
7
+ }
8
+ }
@@ -4,7 +4,7 @@ export function useDelayed<Args extends any[]>(
4
4
  callback: (...args: Args) => void | Promise<void>,
5
5
  dependencies: any[],
6
6
  delay = 100,
7
- maxDelay?: number
7
+ maxDelay: number|undefined = undefined
8
8
  ) {
9
9
  const argsRef = useRef<Args | undefined>(undefined);
10
10
  const timeoutRef = useRef<any>(undefined);
@@ -1,8 +1,9 @@
1
- import {useLayoutEffect, useRef} from "react";
1
+ import {useRef} from "react";
2
+ import { useClientLayoutEffect } from "./useClientLayoutEffect";
2
3
 
3
4
  export function useMousePosition() {
4
5
  const position = useRef({ x: 0, y: 0 });
5
- useLayoutEffect(() => {
6
+ useClientLayoutEffect(() => {
6
7
  const setFromEvent = (e: MouseEvent) => {
7
8
  position.current = { x: e.clientX, y: e.clientY };
8
9
  };
@@ -151,7 +151,6 @@ function GridItem({
151
151
  // Other
152
152
 
153
153
  // Render Functions
154
-
155
154
  return (
156
155
  <InlineBlock
157
156
  style={style}
@@ -1,11 +1,9 @@
1
1
  import * as React from 'react';
2
2
  import { RbmComponentProps } from '../RbmComponentProps';
3
-
4
3
  import styles from './layout.scss';
5
- import { withMemo } from '../../helper/withMemo';
6
4
  import classNames from 'classnames';
7
5
  import { withForwardRef } from "../../helper/withForwardRef";
8
- import { ComponentRef, ForwardedRef } from "react";
6
+ import { ForwardedRef } from "react";
9
7
 
10
8
  export type GrowProps = RbmComponentProps<{
11
9
  center?: boolean;
@@ -48,4 +46,4 @@ export const Grow = withForwardRef(function Grow({ className, children, center =
48
46
  {children}
49
47
  </div>
50
48
  );
51
- }, styles)
49
+ }, styles);
@@ -1,13 +1,14 @@
1
1
  import * as React from 'react';
2
- import { ComponentRef, ForwardedRef, PropsWithChildren, ReactElement, ReactNode, RefAttributes } from 'react';
2
+ import { ComponentRef, ForwardedRef, PropsWithChildren } from 'react';
3
3
  import { Override } from '../../TypeHelpers';
4
+ import { withForwardRef } from "../../helper/withForwardRef";
4
5
 
5
6
  export type ViewProps<AsType extends keyof JSX.IntrinsicElements> = PropsWithChildren<
6
7
  Override<React.ComponentPropsWithoutRef<AsType>, { as?: AsType; children?: React.ReactNode }>
7
8
  >;
8
9
 
9
- function View<AsType extends keyof JSX.IntrinsicElements>(
10
- { children, as, ...otherProps }: ViewProps<AsType>,
10
+ export const View = withForwardRef(function View<AsType extends keyof JSX.IntrinsicElements>(
11
+ {children, as, ...otherProps}: ViewProps<AsType>,
11
12
  ref?: ForwardedRef<ComponentRef<AsType>>
12
13
  ) {
13
14
  // Variables
@@ -31,10 +32,4 @@ function View<AsType extends keyof JSX.IntrinsicElements>(
31
32
  ref,
32
33
  };
33
34
  return React.createElement(element, props, children);
34
- }
35
-
36
- // Need ViewMemo for autocompletion of phpstorm
37
- const ViewMemo: <AsType extends keyof JSX.IntrinsicElements>(
38
- props: ViewProps<AsType> & RefAttributes<ComponentRef<AsType>>
39
- ) => ReactNode | null = React.memo(React.forwardRef(View));
40
- export { ViewMemo as View };
35
+ }, undefined, "all");
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
- import { ComponentRef, DOMAttributes, ForwardedRef, ReactElement, ReactNode, RefAttributes } from 'react';
2
+ import { ComponentRef, DOMAttributes, ForwardedRef } from 'react';
3
3
  import { View, ViewProps } from './View';
4
+ import { withForwardRef } from "../../helper/withForwardRef";
4
5
 
5
6
  export type ViewWithoutListenersProps<AsType extends keyof JSX.IntrinsicElements> = Omit<
6
7
  ViewProps<AsType>,
@@ -11,7 +12,7 @@ export type ViewWithoutListenersProps<AsType extends keyof JSX.IntrinsicElements
11
12
  __html: string | TrustedHTML;
12
13
  } | undefined; };
13
14
 
14
- function ViewWithoutListeners<AsType extends keyof JSX.IntrinsicElements>(
15
+ export const ViewWithoutListeners = withForwardRef(function ViewWithoutListeners<AsType extends keyof JSX.IntrinsicElements>(
15
16
  { children, ...props }: ViewWithoutListenersProps<AsType>,
16
17
  ref?: ForwardedRef<ComponentRef<AsType>>
17
18
  ) {
@@ -35,10 +36,4 @@ function ViewWithoutListeners<AsType extends keyof JSX.IntrinsicElements>(
35
36
  {children}
36
37
  </View>
37
38
  );
38
- }
39
-
40
- // Need ViewWithoutListenersMemo for autocompletion of phpstorm
41
- const ViewWithoutListenersMemo: <AsType extends keyof JSX.IntrinsicElements>(
42
- props: ViewWithoutListenersProps<AsType> & RefAttributes<ComponentRef<AsType>>
43
- ) => ReactNode = React.memo(React.forwardRef(ViewWithoutListeners));
44
- export { ViewWithoutListenersMemo as ViewWithoutListeners };
39
+ }, undefined, "all");
@@ -5,12 +5,13 @@ import {IconSource} from '../Icon/Icon';
5
5
  import {Block} from '../Layout/Block';
6
6
  import classNames from 'classnames';
7
7
  import styles from './menu.scss';
8
- import {useEffect, useLayoutEffect, useRef, useState} from 'react';
8
+ import {useEffect, useRef, useState} from 'react';
9
9
  import {withRenderBrowserOnly} from '../../helper/withRenderBrowserOnly';
10
10
  import {useWindow} from '../../WindowContext/WindowContext';
11
11
  import {MenuItem} from "./MenuItem";
12
12
  import {MenuCloseContextProvider} from "./MenuCloseContext";
13
13
  import {createPortal} from "react-dom";
14
+ import { useClientLayoutEffect } from "../Hooks/useClientLayoutEffect";
14
15
 
15
16
  export type MenuItemType = {
16
17
  label: string;
@@ -78,26 +79,25 @@ export const Menu = withMemo(
78
79
  window?.addEventListener('mousedown', listener, {capture: true});
79
80
  window?.addEventListener('touchstart', listener, {capture: true});
80
81
  return () => {
81
- window?.removeEventListener('mousedown', listener, {capture: true})
82
- window?.removeEventListener('touchstart', listener, {capture: true})
82
+ window?.removeEventListener('mousedown', listener, {capture: true});
83
+ window?.removeEventListener('touchstart', listener, {capture: true});
83
84
  };
84
85
  }
85
86
  return undefined;
86
87
  }, [isOpen, onClose, window]);
87
88
 
88
- useLayoutEffect(() => {
89
+ useClientLayoutEffect(() => {
89
90
  if (!isOpen) {
90
91
  return;
91
92
  }
92
- let elem = window?.document.body.querySelector("." + MENU_CONTAINER_CLASS);
93
+ let elem = window?.document.body.querySelector(`.${ MENU_CONTAINER_CLASS}`);
93
94
  if (!elem) {
94
95
  elem = window?.document.body;
95
96
  }
96
- elem?.appendChild(portalContainer)
97
+ elem?.appendChild(portalContainer);
97
98
  }, [isOpen, portalContainer, window?.document.body]);
98
99
 
99
-
100
- useLayoutEffect(() => {
100
+ useClientLayoutEffect(() => {
101
101
  if (!menuRef.current) {
102
102
  return;
103
103
  }
@@ -114,7 +114,7 @@ export const Menu = withMemo(
114
114
  setInnerX(newX);
115
115
  }, [offsetX, window?.innerWidth, x]);
116
116
 
117
- useLayoutEffect(() => {
117
+ useClientLayoutEffect(() => {
118
118
  if (!menuRef.current) {
119
119
  return;
120
120
  }
@@ -1,6 +1,5 @@
1
1
  import { CSSProperties, ReactNode } from 'react';
2
2
  import { Recursive } from '../TypeHelpers';
3
- import { URecord } from "@ainias42/js-helper";
4
3
 
5
4
  export type RbmChildWithoutString = Recursive<JSX.Element | undefined | null | RbmChildWithoutString[]> | false;
6
5
  export type WithNoStringProps =
@@ -7,13 +7,11 @@ import { Grow } from '../../Layout/Grow';
7
7
  import { Text, TEXT_SIZE } from '../../Text/Text';
8
8
  import { Block } from '../../Layout/Block';
9
9
  import { Clickable } from '../../Clickable/Clickable';
10
-
11
10
  import styles from './spoiler.scss';
12
11
  import classNames from 'classnames';
13
12
  import { OptionalListener, useListener } from '../../Hooks/useListener';
14
13
  import { Icon, IconSource } from '../../Icon/Icon';
15
14
  import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons';
16
- import { IconProp } from '@fortawesome/fontawesome-svg-core';
17
15
 
18
16
  export type SpoilerProps<OnClickData> = RbmComponentProps<
19
17
  {
@@ -89,7 +87,7 @@ function Spoiler<OnClickData>({
89
87
  style={style}
90
88
  >
91
89
  <Flex horizontal={true}>
92
- <Grow __allowChildren={"all"}>{titleComponent}</Grow>
90
+ <Grow __allowChildren="all">{titleComponent}</Grow>
93
91
  {icon ? <Icon icon={icon} className={styles.icon} /> : null}
94
92
  </Flex>
95
93
  <Block className={styles.bodyContainer}>
@@ -79,7 +79,6 @@ function Toast<ActionData, DismissedData>({
79
79
 
80
80
  // Render Functions
81
81
  if (isHidden) {
82
- console.log("LOG-d isHidden");
83
82
  return null;
84
83
  }
85
84
 
@@ -6,17 +6,61 @@ import styles from './toast.scss';
6
6
  import classNames from 'classnames';
7
7
  import { withMemo } from '../../helper/withMemo';
8
8
  import { EmptyProps } from '../../helper/EmptyProps';
9
+ import { useCallback, useRef, useState } from "react";
10
+ import { ObjectHelper, URecord } from "@ainias42/js-helper";
11
+ import { Toast } from "./Toast";
12
+ import { Text } from "../Text/Text";
13
+ import { ToastContext } from "./ToastContext";
9
14
 
10
15
  export type ToastContainerProps = RbmComponentProps<EmptyProps>;
11
16
 
12
- function ToastContainer({ className, children, style }: ToastContainerProps) {
17
+ function ToastContainer({className, children, style}: ToastContainerProps) {
13
18
  // Variables
14
19
 
15
20
  // States
21
+ const lastId = useRef(0);
22
+ const [toasts, setToasts] = useState<URecord<number, {
23
+ id: number,
24
+ text: string,
25
+ duration: number,
26
+ action?: { name: string, onClick: (data?: any) => void, onClickData?: any }
27
+ }>>({});
16
28
 
17
29
  // Refs
18
30
 
19
31
  // Callbacks
32
+ const removeToast = useCallback((id: number) => {
33
+ setToasts((oldToasts) => {
34
+ const newToasts = {...oldToasts};
35
+ delete newToasts[id];
36
+ return newToasts;
37
+ });
38
+ }, []);
39
+
40
+ const addToast = useCallback((
41
+ text: string,
42
+ action?: {
43
+ name: string,
44
+ onClick: (data?: any) => void,
45
+ onClickData?: any
46
+ },
47
+ duration = 2500
48
+ ) => {
49
+ lastId.current++;
50
+ const id = lastId.current;
51
+
52
+ setToasts((oldToasts) => {
53
+ return {
54
+ ...oldToasts,
55
+ [id]: {
56
+ id,
57
+ text,
58
+ duration,
59
+ action
60
+ }
61
+ };
62
+ });
63
+ }, []);
20
64
 
21
65
  // Effects
22
66
 
@@ -25,9 +69,21 @@ function ToastContainer({ className, children, style }: ToastContainerProps) {
25
69
  // Render Functions
26
70
 
27
71
  return (
28
- <Container className={classNames(styles.toastContainer, className)} fluid __allowChildren="all" style={style}>
72
+ <ToastContext.Provider value={addToast}>
29
73
  {children}
30
- </Container>
74
+ <Container className={classNames(styles.toastContainer, className)} fluid __allowChildren="all"
75
+ style={style}>
76
+ {ObjectHelper.values(toasts).map((toast) => <Toast key={toast.id}
77
+ timeToShow={toast.duration}
78
+ onDismissed={removeToast}
79
+ onDismissedData={toast.id} {...(toast.action ? {
80
+ ...toast.action,
81
+ actionName: toast.action.name
82
+ } : {})}>
83
+ <Text>{toast.text}</Text>
84
+ </Toast>)}
85
+ </Container>
86
+ </ToastContext.Provider>
31
87
  );
32
88
  }
33
89
 
@@ -0,0 +1,9 @@
1
+ import { createContext, useContext } from "react";
2
+
3
+ export const ToastContext = createContext<<Data>(text: string, action?: {name: string, onClick: (data?: Data) => void, onClickData?: Data }, duration?: number) => void>(() => {
4
+ console.error("ToastContext not initialized");
5
+ });
6
+
7
+ export function useToast() {
8
+ return useContext(ToastContext);
9
+ }
@@ -1,5 +1,4 @@
1
1
  import * as React from 'react';
2
- import { useCallback } from 'react';
3
2
  import { RbmComponentProps } from '../RbmComponentProps';
4
3
 
5
4
  import styles from './topBar.scss';
@@ -12,13 +11,12 @@ export type TopBarButtonProps = RbmComponentProps<{
12
11
  }>;
13
12
 
14
13
  function TopBarButton({ disabled = false, onClick, className, children, ...rbmProps }: TopBarButtonProps) {
15
- const cb = useCallback(() => (onClick ? onClick() : null), [onClick]);
16
14
  return (
17
15
  <a
18
16
  role="button"
19
17
  {...rbmProps}
20
- onClick={cb}
21
- className={classNames(styles.button, { [styles.disabled]: disabled }, className)}
18
+ onClick={onClick}
19
+ className={classNames(styles.button, { [styles.disabled]: disabled, [styles.active]: !disabled && onClick }, className)}
22
20
  >
23
21
  {children}
24
22
  </a>
@@ -24,6 +24,10 @@
24
24
  }
25
25
 
26
26
  .button {
27
+ &.active {
28
+ cursor: pointer;
29
+ }
30
+
27
31
  display: block;
28
32
  padding: 0.5rem 1rem;
29
33
  color: #0d3efd; // TODO change color
@@ -6,7 +6,7 @@ export function withRenderBrowserOnly<C extends ComponentType<any>>(Component: C
6
6
 
7
7
  const displayName = `WithRenderBrowserOnly(${Component.displayName || Component.name})`;
8
8
 
9
- const HocComponent = ({ children, ...props }: Props, ref?: ForwardedRef<RefType>) => {
9
+ function HocComponent({ children, ...props }: Props, ref?: ForwardedRef<RefType>) {
10
10
  const [isBrowser, setIsBrowser] = useState(false);
11
11
 
12
12
  useEffect(() => setIsBrowser(true), []);
@@ -24,7 +24,7 @@ export function withRenderBrowserOnly<C extends ComponentType<any>>(Component: C
24
24
  // @ts-ignore
25
25
  <Component {...(newProps as Props)}>{children}</Component>
26
26
  );
27
- };
27
+ }
28
28
  HocComponent.displayName = displayName;
29
29
  return HocComponent as C;
30
30
  }
@@ -1,26 +1,26 @@
1
- .full-height {
1
+ :global(.full-height) {
2
2
  height: 100%;
3
3
  }
4
4
 
5
- .full-min-height {
5
+ :global(.full-min-height) {
6
6
  min-height: 100%;
7
7
  }
8
8
 
9
- .scrollable {
9
+ :global(.scrollable) {
10
10
  overflow-y: auto;
11
11
  }
12
12
 
13
- .full-width {
13
+ :global(.full-width) {
14
14
  width: 100%;
15
15
  }
16
16
 
17
- .flat-hidden {
17
+ :global(.flat-hidden) {
18
18
  @include design($flat) {
19
19
  display: none;
20
20
  }
21
21
  }
22
22
 
23
- .material-hidden {
23
+ :global(.material-hidden) {
24
24
  @include design($material) {
25
25
  display: none;
26
26
  }
@@ -1,3 +1,5 @@
1
+ @import "designMixin";
2
+
1
3
  * {
2
4
  box-sizing: border-box;
3
5
  -webkit-font-smoothing: antialiased;
@@ -1,5 +1,5 @@
1
- @import 'bootstrap/scss/functions';
2
- @import 'bootstrap/scss/variables';
1
+ @import '~bootstrap/scss/functions';
2
+ @import '~bootstrap/scss/variables';
3
3
 
4
4
  $classPrefix: "rbm-";
5
5
 
package/webpack.config.js CHANGED
@@ -28,7 +28,7 @@ module.exports = (env) => {
28
28
  output: {
29
29
  filename: 'bootstrapReactMobile.js',
30
30
  path: path.resolve(__dirname, 'dist'),
31
- library: { type: 'umd' },
31
+ library: { type: 'commonjs-static' },
32
32
  clean: true,
33
33
  globalObject: 'this',
34
34
  },
@@ -63,6 +63,7 @@ module.exports = (env) => {
63
63
  esModule: false,
64
64
  modules: {
65
65
  localIdentName: '[local]__[hash:base64:5]',
66
+ exportLocalsConvention: 'camel-case'
66
67
  },
67
68
  },
68
69
  },
@@ -1,46 +0,0 @@
1
- @keyframes material-new-site {
2
- 0% {
3
- transform: translate(0, 100%);
4
- z-index: 1;
5
- }
6
- 100% {
7
- transform: translate(0, 0);
8
- z-index: 1;
9
- }
10
- }
11
-
12
- @keyframes flat-new-site {
13
- 0% {
14
- transform: translate(100%, 0);
15
- z-index: 1;
16
- }
17
- 100% {
18
- transform: translate(0, 0);
19
- z-index: 1;
20
- }
21
- }
22
-
23
- .animation-new-site {
24
- background: green;
25
- @include design($material) {
26
- animation: material-new-site;
27
- animation-duration: $animationDurationMaterial;
28
- }
29
- @include design($flat) {
30
- animation: flat-new-site;
31
- animation-duration: $animationDurationMaterial;
32
- }
33
- }
34
-
35
- .animation-end-site {
36
- @include design($material) {
37
- animation: material-new-site;
38
- animation-duration: $animationDurationMaterial;
39
- animation-direction: reverse;
40
- }
41
- @include design($flat) {
42
- animation: flat-new-site;
43
- animation-duration: $animationDurationMaterial;
44
- animation-direction: reverse;
45
- }
46
- }
@@ -1,35 +0,0 @@
1
- @use 'sass:selector';
2
-
3
- @mixin design($designName) {
4
- @if & {
5
- @at-root #{selector.nest('.'+$designName, &)} {
6
- @content
7
- }
8
- } @else {
9
- .#{$designName} {
10
- @content
11
- }
12
- }
13
- }
14
-
15
- @mixin subPrefix($className) {
16
- .#{$classPrefix+$className} {
17
- @content
18
- }
19
- }
20
-
21
- @mixin prefix($className, $concatSelectors: false) {
22
- @if $concatSelectors == true {
23
- &.#{$classPrefix+$className} {
24
- @content
25
- }
26
- } @else if ($concatSelectors != false) {
27
- #{$concatSelectors}.#{$classPrefix+$className} {
28
- @content
29
- }
30
- } @else {
31
- @include subPrefix($className) {
32
- @content
33
- }
34
- }
35
- }