@performant-software/semantic-components 0.5.5 → 0.5.6

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.
@@ -12,6 +12,7 @@ import {
12
12
  Segment
13
13
  } from 'semantic-ui-react';
14
14
  import i18n from '../i18n/i18n';
15
+ import ModalContext from '../context/ModalContext';
15
16
  import './VideoFrameSelector.css';
16
17
 
17
18
  type Props = {
@@ -46,91 +47,102 @@ const VideoFrameSelector = (props: Props) => {
46
47
  {...props.button}
47
48
  onClick={() => setModal(true)}
48
49
  />
49
- <Modal
50
- centered={false}
51
- className='video-frame-selector'
52
- open={modal}
53
- size='small'
54
- >
55
- <Modal.Header
56
- content={props.title}
57
- />
58
- <Modal.Content>
59
- <Segment>
60
- <video
61
- crossOrigin='anonymous'
62
- onLoadedMetadata={() => videoRef.current && setDuration(videoRef.current.duration)}
63
- ref={videoRef}
64
- src={props.src}
65
- />
66
- </Segment>
67
- <Grid
68
- columns={2}
50
+ <ModalContext.Consumer>
51
+ { (mountNode) => (
52
+ <Modal
53
+ centered={false}
54
+ className='video-frame-selector'
55
+ mountNode={mountNode}
56
+ open={modal}
57
+ size='small'
69
58
  >
70
- <Grid.Column>
71
- <div>
72
- <Label
73
- content={i18n.t('VideoFrameSelector.labels.interval', { count: interval })}
59
+ <Modal.Header
60
+ content={props.title}
61
+ />
62
+ <Modal.Content>
63
+ <Segment>
64
+ <video
65
+ crossOrigin='anonymous'
66
+ onLoadedMetadata={() => videoRef.current && setDuration(videoRef.current.duration)}
67
+ ref={videoRef}
68
+ src={props.src}
74
69
  />
75
- </div>
76
- <Input
77
- min={MIN_INTERVAL}
78
- max={MAX_INTERVAL}
79
- name='duration'
80
- onChange={(e, { value }) => setInterval(Number(value))}
81
- step={INTERVAL_STEP}
82
- type='range'
83
- value={interval}
84
- />
85
- </Grid.Column>
86
- <Grid.Column
87
- textAlign='right'
88
- >
70
+ </Segment>
71
+ <Grid
72
+ columns={2}
73
+ >
74
+ <Grid.Column>
75
+ <div>
76
+ <Label
77
+ content={i18n.t('VideoFrameSelector.labels.interval', { count: interval })}
78
+ />
79
+ </div>
80
+ <Input
81
+ aria-label='Interval Selector'
82
+ min={MIN_INTERVAL}
83
+ max={MAX_INTERVAL}
84
+ name='duration'
85
+ onChange={(e, { value }) => setInterval(Number(value))}
86
+ step={INTERVAL_STEP}
87
+ type='range'
88
+ value={interval}
89
+ />
90
+ </Grid.Column>
91
+ <Grid.Column
92
+ textAlign='right'
93
+ >
94
+ <Button
95
+ aria-label='Previous Frame'
96
+ basic
97
+ disabled={time === 0}
98
+ icon='arrow left'
99
+ onClick={() => setTime(Math.max(time - interval, 0))}
100
+ />
101
+ <Button
102
+ aria-label='Next Frame'
103
+ basic
104
+ disabled={time === duration}
105
+ icon='arrow right'
106
+ onClick={() => setTime(Math.min(time + interval, duration))}
107
+ />
108
+ </Grid.Column>
109
+ </Grid>
110
+ </Modal.Content>
111
+ <Modal.Actions>
89
112
  <Button
90
- basic
91
- disabled={time === 0}
92
- icon='arrow left'
93
- onClick={() => setTime(Math.max(time - interval, 0))}
113
+ content={i18n.t('Common.buttons.ok')}
114
+ primary
115
+ onClick={() => {
116
+ const video = videoRef.current;
117
+
118
+ if (video && Browser.isBrowser()) {
119
+ const canvas = document.createElement('canvas');
120
+ canvas.width = video.videoWidth;
121
+ canvas.height = video.videoHeight;
122
+
123
+ canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
124
+
125
+ canvas.toBlob((blob) => {
126
+ const file = new File([blob], 'test.png', {
127
+ lastModified: new Date().getTime(),
128
+ type: blob.type
129
+ });
130
+
131
+ props.onSelect(file);
132
+ setModal(false);
133
+ });
134
+ }
135
+ }}
94
136
  />
95
137
  <Button
96
138
  basic
97
- disabled={time === duration}
98
- icon='arrow right'
99
- onClick={() => setTime(Math.min(time + interval, duration))}
139
+ content={i18n.t('Common.buttons.cancel')}
140
+ onClick={() => setModal(false)}
100
141
  />
101
- </Grid.Column>
102
- </Grid>
103
- </Modal.Content>
104
- <Modal.Actions>
105
- <Button
106
- content={i18n.t('Common.buttons.ok')}
107
- primary
108
- onClick={() => {
109
- const video = videoRef.current;
110
-
111
- if (video && Browser.isBrowser()) {
112
- const canvas = document.createElement('canvas');
113
- canvas.width = video.videoWidth;
114
- canvas.height = video.videoHeight;
115
-
116
- canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
117
-
118
- canvas.toBlob((blob) => {
119
- const file = new File([blob], 'test.png', { lastModified: new Date().getTime(), type: blob.type });
120
- props.onSelect(file);
121
- setModal(false);
122
- });
123
- }
124
- }}
125
- />
126
- <Button
127
- content={i18n.t('Common.buttons.cancel')}
128
- inverted
129
- onClick={() => setModal(false)}
130
- primary
131
- />
132
- </Modal.Actions>
133
- </Modal>
142
+ </Modal.Actions>
143
+ </Modal>
144
+ )}
145
+ </ModalContext.Consumer>
134
146
  </>
135
147
  );
136
148
  };
@@ -1,7 +1,8 @@
1
1
  // @flow
2
2
 
3
- import React, { type Element } from 'react';
4
- import { Embed, Modal } from 'semantic-ui-react';
3
+ import React, { type Element, useEffect, useRef } from 'react';
4
+ import { Embed, Modal, Ref } from 'semantic-ui-react';
5
+ import ModalContext from '../context/ModalContext';
5
6
  import './VideoPlayer.css';
6
7
 
7
8
  type Props = {
@@ -11,39 +12,66 @@ type Props = {
11
12
  onClose: () => void,
12
13
  open: boolean,
13
14
  placeholder?: ?string,
15
+ placeholderAlt?: string,
14
16
  size?: string,
15
17
  video: string
16
18
  };
17
19
 
18
- const VideoPlayer = (props: Props) => (
19
- <Modal
20
- centered={false}
21
- className='video-player'
22
- closeIcon
23
- onClose={props.onClose.bind(this)}
24
- open={props.open}
25
- size={props.size}
26
- >
27
- <Modal.Content>
28
- { props.embedded && (
29
- <Embed
30
- active={props.autoPlay}
31
- icon={props.icon}
32
- iframe={props.autoPlay ? { allow: 'autoplay' } : undefined}
33
- placeholder={props.placeholder}
34
- url={`${props.video}${props.autoPlay ? '?autoplay=true' : ''}`}
35
- />
36
- )}
37
- { !props.embedded && (
38
- <video
39
- autoPlay={props.autoPlay}
40
- controls
41
- src={props.video}
42
- />
20
+ const VideoPlayer = (props: Props) => {
21
+ const embedRef = useRef();
22
+
23
+ /**
24
+ * Work-around to set the "alt" attribute on the placeholder <img> element if provided.
25
+ */
26
+ useEffect(() => {
27
+ if (embedRef && embedRef.current && props.placeholderAlt) {
28
+ const placeholder = embedRef.current.querySelector('.placeholder');
29
+
30
+ if (placeholder) {
31
+ placeholder.setAttribute('alt', props.placeholderAlt);
32
+ }
33
+ }
34
+ }, [embedRef, props.placeholderAlt]);
35
+
36
+ return (
37
+ <ModalContext.Consumer>
38
+ { (mountNode) => (
39
+ <Modal
40
+ centered={false}
41
+ className='video-player'
42
+ closeIcon
43
+ mountNode={mountNode}
44
+ onClose={props.onClose.bind(this)}
45
+ open={props.open}
46
+ size={props.size}
47
+ >
48
+ <Modal.Content>
49
+ { props.embedded && (
50
+ <Ref
51
+ innerRef={embedRef}
52
+ >
53
+ <Embed
54
+ active={props.autoPlay}
55
+ icon={props.icon}
56
+ iframe={props.autoPlay ? { allow: 'autoplay' } : undefined}
57
+ placeholder={props.placeholder}
58
+ url={`${props.video}${props.autoPlay ? '?autoplay=true' : ''}`}
59
+ />
60
+ </Ref>
61
+ )}
62
+ { !props.embedded && (
63
+ <video
64
+ autoPlay={props.autoPlay}
65
+ controls
66
+ src={props.video}
67
+ />
68
+ )}
69
+ </Modal.Content>
70
+ </Modal>
43
71
  )}
44
- </Modal.Content>
45
- </Modal>
46
- );
72
+ </ModalContext.Consumer>
73
+ );
74
+ };
47
75
 
48
76
  VideoPlayer.defaultProps = {
49
77
  autoPlay: false,
@@ -4,6 +4,7 @@ import React, { type ComponentType, useState } from 'react';
4
4
  import SyntaxHighlighter from 'react-syntax-highlighter';
5
5
  import { Button, Modal } from 'semantic-ui-react';
6
6
  import i18n from '../i18n/i18n';
7
+ import ModalContext from '../context/ModalContext';
7
8
 
8
9
  type Props = {
9
10
  highlighter?: any,
@@ -21,39 +22,44 @@ const ViewXML = (props: Props) => {
21
22
  const openerProps = props.opener.props;
22
23
 
23
24
  return (
24
- <>
25
- <OpenerComponent
26
- {...openerProps}
27
- className='view-xml-trigger'
28
- onClick={() => setShowModal(true)}
29
- />
30
- <Modal
31
- className='view-xml-modal'
32
- centered={false}
33
- open={showModal}
34
- onClose={() => setShowModal(false)}
35
- >
36
- <Modal.Header
37
- content={i18n.t('ViewXML.title')}
38
- />
39
- <Modal.Content>
40
- <SyntaxHighlighter
41
- language='xml'
42
- style={props.highlighter}
43
- >
44
- { props.xml }
45
- </SyntaxHighlighter>
46
- </Modal.Content>
47
- <Modal.Actions>
48
- <Button
49
- content='Close'
50
- inverted
51
- primary
52
- onClick={() => setShowModal(false)}
25
+ <ModalContext.Consumer>
26
+ { (mountNode) => (
27
+ <>
28
+ <OpenerComponent
29
+ {...openerProps}
30
+ className='view-xml-trigger'
31
+ onClick={() => setShowModal(true)}
53
32
  />
54
- </Modal.Actions>
55
- </Modal>
56
- </>
33
+ <Modal
34
+ className='view-xml-modal'
35
+ closeIcon
36
+ centered={false}
37
+ mountNode={mountNode}
38
+ open={showModal}
39
+ onClose={() => setShowModal(false)}
40
+ >
41
+ <Modal.Header
42
+ content={i18n.t('ViewXML.title')}
43
+ />
44
+ <Modal.Content>
45
+ <SyntaxHighlighter
46
+ language='xml'
47
+ style={props.highlighter}
48
+ >
49
+ { props.xml }
50
+ </SyntaxHighlighter>
51
+ </Modal.Content>
52
+ <Modal.Actions>
53
+ <Button
54
+ basic
55
+ content={i18n.t('Common.buttons.close')}
56
+ onClick={() => setShowModal(false)}
57
+ />
58
+ </Modal.Actions>
59
+ </Modal>
60
+ </>
61
+ )}
62
+ </ModalContext.Consumer>
57
63
  );
58
64
  };
59
65
 
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+
3
+ const ModalContext = React.createContext();
4
+
5
+ export default ModalContext;
@@ -16,6 +16,7 @@ export { default as ColorPickerModal } from './components/ColorPickerModal';
16
16
  export { default as useDataList } from './components/DataList';
17
17
  export { default as DataTable } from './components/DataTable';
18
18
  export { default as DataView } from './components/DataView';
19
+ export { default as DatabaseView } from './components/DatabaseView';
19
20
  export { default as DateInput } from './components/DateInput';
20
21
  export { default as DatePicker } from './components/DatePicker';
21
22
  export { default as DescriptorField } from './components/DescriptorField';