playbook_ui 15.7.0.pre.alpha.play2607setheightofeditor13370 → 15.7.0.pre.alpha.play258013248

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_rich_text_editor/TipTap/Toolbar.tsx +1 -1
  3. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +3 -8
  4. data/app/pb_kits/playbook/pb_rich_text_editor/_tiptap_styles.scss +0 -53
  5. data/app/pb_kits/playbook/pb_rich_text_editor/docs/example.yml +0 -2
  6. data/app/pb_kits/playbook/pb_rich_text_editor/docs/index.js +1 -3
  7. data/app/pb_kits/playbook/pb_text_input/_text_input.tsx +3 -41
  8. data/app/pb_kits/playbook/pb_text_input/docs/example.yml +0 -2
  9. data/app/pb_kits/playbook/pb_text_input/docs/index.js +0 -1
  10. data/app/pb_kits/playbook/pb_text_input/index.js +8 -49
  11. data/app/pb_kits/playbook/pb_text_input/text_input.rb +1 -5
  12. data/app/pb_kits/playbook/pb_text_input/text_input.test.js +0 -53
  13. data/app/pb_kits/playbook/pb_textarea/_textarea.tsx +2 -38
  14. data/app/pb_kits/playbook/pb_textarea/docs/example.yml +0 -2
  15. data/app/pb_kits/playbook/pb_textarea/docs/index.js +0 -1
  16. data/app/pb_kits/playbook/pb_textarea/index.ts +5 -62
  17. data/app/pb_kits/playbook/pb_textarea/textarea.html.erb +0 -1
  18. data/app/pb_kits/playbook/pb_textarea/textarea.rb +0 -8
  19. data/app/pb_kits/playbook/pb_textarea/textarea.test.js +2 -57
  20. data/dist/chunks/{_typeahead-D0GNUBXn.js → _typeahead-Ckz1ce-2.js} +2 -2
  21. data/dist/chunks/{lib-DxCgrqqG.js → lib-DxDBrGZX.js} +1 -1
  22. data/dist/chunks/vendor.js +3 -3
  23. data/dist/playbook-rails-react-bindings.js +1 -1
  24. data/dist/playbook-rails.js +1 -1
  25. data/dist/playbook.css +1 -1
  26. data/lib/playbook/forms/builder/form_field_builder.rb +0 -2
  27. data/lib/playbook/version.rb +1 -1
  28. metadata +4 -15
  29. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_height.jsx +0 -71
  30. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_height.md +0 -1
  31. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_min_heigh.md +0 -1
  32. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_min_height.jsx +0 -71
  33. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_emoji_mask.html.erb +0 -7
  34. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_emoji_mask.jsx +0 -24
  35. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_emoji_mask.md +0 -2
  36. data/app/pb_kits/playbook/pb_textarea/docs/_textarea_emoji_mask.html.erb +0 -5
  37. data/app/pb_kits/playbook/pb_textarea/docs/_textarea_emoji_mask.jsx +0 -24
  38. data/app/pb_kits/playbook/pb_textarea/docs/_textarea_emoji_mask.md +0 -1
  39. data/app/pb_kits/playbook/utilities/emojiMask.ts +0 -42
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f960f22bca9b3635502362441b26a13583eb183fcdebab46ebbca3f5b2b64d33
4
- data.tar.gz: 37dd6c333df8bc2149be578ef208c32fea70e3ebdec053a8ab180ec5bf56e1d7
3
+ metadata.gz: a57b87c794ebb9c526328411d074cf50c56b92e554eea530bc34ab79f009b9d7
4
+ data.tar.gz: 14aa366eb5f3af416b537e4d51cc70fcec656cfb5b7be7fa754f0fdf45e54cf0
5
5
  SHA512:
6
- metadata.gz: 694f79e8ddf8ab1bd308e0d0f85faacbd856f66dfbb52f728074ff1721d673b0d4d32513c0aa5dd4c05f652aeb73d1ae4f5c77258fedbdb26b17f80fdcbf1e3d
7
- data.tar.gz: b8cb5e6390f7a57b562a29dfa341ec33860bdee17c24df89ead92d06d01ae82bf9283600c0d0f4aedcf9b6dafc1b0cddb2eebd4bebdf5118b4fd10a356e65004
6
+ metadata.gz: 6b3ec5d9f16652c8cd619e3410315d7ce5559cebf78811127ebd624d33bc7987c0846fcc6c26b8daada7438c9896894b0fb4abb81816eeb98a664d725778da0d
7
+ data.tar.gz: d24a169b7c3712bdeb27dff6a886128a0c4c5b94f4d91a6d9beb45eaa33d9f459a262d9b80582a0e3f9d16f38f0db76586a9a26de71dfb5bf286766aeb6931bf
@@ -4,7 +4,7 @@ import Flex from "../../pb_flex/_flex";
4
4
  import FlexItem from "../../pb_flex/_flex_item";
5
5
  import SectionSeparator from "../../pb_section_separator/_section_separator";
6
6
 
7
- import EditorButton from "./EditorButton";
7
+ import EditorButton from "./EditorButton";
8
8
  import ToolbarDropdown from "./ToolbarDropdown";
9
9
  import ToolbarNodes from "./ToolbarNodes";
10
10
  import { ToolbarTypes } from "./EditorTypes";
@@ -44,8 +44,6 @@ type RichTextEditorProps = {
44
44
  name?: string,
45
45
  onChange: (html: string, text: string) => void,
46
46
  placeholder?: string,
47
- inputHeight?: "sm" | "md" | "lg",
48
- inputMinHeight?: "sm" | "md" | "lg",
49
47
  simple?: boolean,
50
48
  sticky?: boolean,
51
49
  template: string,
@@ -70,8 +68,6 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
70
68
  name,
71
69
  onChange = noop,
72
70
  placeholder,
73
- inputHeight,
74
- inputMinHeight,
75
71
  simple = false,
76
72
  sticky = false,
77
73
  template = '',
@@ -218,10 +214,9 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
218
214
  {
219
215
  advancedEditor ? (
220
216
  <div
221
- className={classnames(
222
- "pb_rich_text_editor_advanced_container",
223
- { [`input_height_${inputHeight}`]: !!inputHeight,[`input_min_height_${inputMinHeight}`]: !!inputMinHeight ,["toolbar-active"]: shouldShowToolbar }
224
- )}
217
+ className={classnames("pb_rich_text_editor_advanced_container", {
218
+ ["toolbar-active"]: shouldShowToolbar,
219
+ })}
225
220
  >
226
221
  {shouldShowToolbar && (
227
222
  <EditorToolbar editor={advancedEditor}
@@ -205,59 +205,6 @@
205
205
  }
206
206
  }
207
207
  }
208
-
209
- .pb_rich_text_editor_advanced_container.input_height_sm {
210
- div {
211
- .tiptap.ProseMirror {
212
- height: 131px;
213
- overflow: auto;
214
- }
215
- }
216
- }
217
-
218
- .pb_rich_text_editor_advanced_container.input_height_md {
219
- div {
220
- .tiptap.ProseMirror {
221
- height: 180px;
222
- overflow: auto;
223
- }
224
- }
225
- }
226
-
227
- .pb_rich_text_editor_advanced_container.input_height_lg {
228
- div {
229
- .tiptap.ProseMirror {
230
- height: 230px;
231
- overflow: auto;
232
- }
233
- }
234
- }
235
-
236
- .pb_rich_text_editor_advanced_container.input_min_height_sm {
237
- div {
238
- .tiptap.ProseMirror {
239
- min-height: 131px;
240
- }
241
- }
242
- }
243
-
244
- .pb_rich_text_editor_advanced_container.input_min_height_md {
245
- div {
246
- .tiptap.ProseMirror {
247
- min-height: 180px;
248
- }
249
- }
250
- }
251
-
252
- .pb_rich_text_editor_advanced_container.input_min_height_lg {
253
- div {
254
- .tiptap.ProseMirror {
255
- min-height: 230px;
256
- }
257
- }
258
- }
259
-
260
-
261
208
  .tiptap-content {
262
209
  @include preview_tiptap_first_child;
263
210
  a {
@@ -29,7 +29,5 @@ examples:
29
29
  # - rich_text_editor_toolbar_bottom: Toolbar Bottom
30
30
  - rich_text_editor_inline: Inline
31
31
  - rich_text_editor_advanced_inline: Advanced (Inline)
32
- - rich_text_editor_advanced_height: Advanced Height
33
- - rich_text_editor_advanced_min_height: Advanced Min Height
34
32
  - rich_text_editor_preview: Preview
35
33
  - rich_text_editor_advanced_preview: Advanced Preview
@@ -16,6 +16,4 @@ export { default as RichTextEditorAdvancedFocus } from './_rich_text_editor_adva
16
16
  export { default as RichTextEditorAdvancedTemplates } from './_rich_text_editor_advanced_templates.jsx'
17
17
  export { default as RichTextEditorAdvancedAttributes } from './_rich_text_editor_advanced_attributes.jsx'
18
18
  export { default as RichTextEditorAdvancedSticky } from './_rich_text_editor_advanced_sticky.jsx'
19
- export { default as RichTextEditorAdvancedInline } from './_rich_text_editor_advanced_inline.jsx'
20
- export { default as RichTextEditorAdvancedHeight } from './_rich_text_editor_advanced_height.jsx'
21
- export { default as RichTextEditorAdvancedMinHeight } from './_rich_text_editor_advanced_min_height.jsx'
19
+ export { default as RichTextEditorAdvancedInline } from './_rich_text_editor_advanced_inline.jsx'
@@ -1,4 +1,4 @@
1
- import React, { forwardRef, ChangeEvent, ClipboardEvent } from 'react'
1
+ import React, { forwardRef, ChangeEvent } from 'react'
2
2
  import classnames from 'classnames'
3
3
 
4
4
  import { globalProps, GlobalProps, domSafeProps } from '../utilities/globalProps'
@@ -12,7 +12,6 @@ import Icon from '../pb_icon/_icon'
12
12
  import colors from '../tokens/exports/_colors.module.scss'
13
13
 
14
14
  import { INPUTMASKS } from './inputMask'
15
- import { stripEmojisForPaste, applyEmojiMask } from '../utilities/emojiMask'
16
15
 
17
16
  type TextInputProps = {
18
17
  aria?: { [key: string]: string },
@@ -20,7 +19,6 @@ type TextInputProps = {
20
19
  data?: { [key: string]: string },
21
20
  dark?: boolean,
22
21
  disabled?: boolean,
23
- emojiMask?: boolean,
24
22
  error?: string,
25
23
  htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
26
24
  id?: string,
@@ -51,7 +49,6 @@ const TextInput = (props: TextInputProps, ref: React.LegacyRef<HTMLInputElement>
51
49
  dark = false,
52
50
  data = {},
53
51
  disabled,
54
- emojiMask = false,
55
52
  error,
56
53
  htmlOptions = {},
57
54
  id,
@@ -105,11 +102,6 @@ const TextInput = (props: TextInputProps, ref: React.LegacyRef<HTMLInputElement>
105
102
  const isMaskedInput = mask && mask in INPUTMASKS
106
103
 
107
104
  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
108
- // Apply emoji mask if enabled using centralized helper
109
- if (emojiMask) {
110
- applyEmojiMask(e.target)
111
- }
112
-
113
105
  if (isMaskedInput) {
114
106
  const inputValue = e.target.value
115
107
 
@@ -142,29 +134,6 @@ const TextInput = (props: TextInputProps, ref: React.LegacyRef<HTMLInputElement>
142
134
  }
143
135
  }
144
136
 
145
- // Handle paste event for emoji mask - updates input value, cursor position, and calls onChange
146
- const handlePaste = (e: ClipboardEvent<HTMLInputElement>) => {
147
- if (emojiMask) {
148
- const pastedText = e.clipboardData.getData('text')
149
- const filteredText = stripEmojisForPaste(pastedText)
150
-
151
- if (pastedText !== filteredText) {
152
- e.preventDefault()
153
- const input = e.currentTarget
154
- const start = input.selectionStart || 0
155
- const end = input.selectionEnd || 0
156
- const currentValue = input.value
157
- const newValue = currentValue.slice(0, start) + filteredText + currentValue.slice(end)
158
- const newCursorPosition = start + filteredText.length
159
-
160
- input.value = newValue
161
- input.selectionStart = input.selectionEnd = newCursorPosition
162
-
163
- onChange({ ...e, target: input, currentTarget: input } as unknown as ChangeEvent<HTMLInputElement>)
164
- }
165
- }
166
- }
167
-
168
137
  const childInput = children ? children.type === "input" : undefined
169
138
 
170
139
  let formattedValue;
@@ -176,16 +145,10 @@ const TextInput = (props: TextInputProps, ref: React.LegacyRef<HTMLInputElement>
176
145
 
177
146
  const errorId = error ? `${id}-error` : undefined
178
147
 
179
- // Set custom handler between emoji mask and input mask
180
- const shouldUseCustomHandler = isMaskedInput || emojiMask
181
-
182
- // Filter out emojiMask from props passed to DOM element
183
- const { emojiMask: _emojiMask, ...domProps } = props
184
-
185
148
  const textInput = (
186
149
  childInput ? React.cloneElement(children, { className: "text_input" }) :
187
150
  (<input
188
- {...domSafeProps(domProps)}
151
+ {...domSafeProps(props)}
189
152
  aria-describedby={errorId}
190
153
  aria-invalid={!!error}
191
154
  autoComplete={typeof autoComplete === "string" ? autoComplete : ( autoComplete ? undefined : "off" )}
@@ -194,8 +157,7 @@ const TextInput = (props: TextInputProps, ref: React.LegacyRef<HTMLInputElement>
194
157
  id={id}
195
158
  key={id}
196
159
  name={name}
197
- onChange={shouldUseCustomHandler ? handleChange : onChange}
198
- onPaste={emojiMask ? handlePaste : undefined}
160
+ onChange={isMaskedInput ? handleChange : onChange}
199
161
  pattern={isMaskedInput ? INPUTMASKS[mask]?.pattern : undefined}
200
162
  placeholder={placeholder || (isMaskedInput ? INPUTMASKS[mask]?.placeholder : undefined)}
201
163
  ref={ref}
@@ -11,7 +11,6 @@ examples:
11
11
  - text_input_mask: Mask
12
12
  - text_input_autocomplete: Autocomplete
13
13
  - text_input_required_indicator: Required Indicator
14
- - text_input_emoji_mask: Emoji Mask
15
14
 
16
15
 
17
16
  react:
@@ -26,7 +25,6 @@ examples:
26
25
  - text_input_sanitize: Sanitized Masked Input
27
26
  - text_input_autocomplete: Autocomplete
28
27
  - text_input_required_indicator: Required Indicator
29
- - text_input_emoji_mask: Emoji Mask
30
28
 
31
29
 
32
30
  swift:
@@ -9,4 +9,3 @@ export { default as TextInputMask } from './_text_input_mask.jsx'
9
9
  export { default as TextInputSanitize } from './_text_input_sanitize.jsx'
10
10
  export { default as TextInputAutocomplete } from './_text_input_autocomplete.jsx'
11
11
  export { default as TextInputRequiredIndicator } from './_text_input_required_indicator.jsx'
12
- export { default as TextInputEmojiMask } from './_text_input_emoji_mask.jsx'
@@ -1,64 +1,26 @@
1
1
  import PbEnhancedElement from "../pb_enhanced_element"
2
2
  import { INPUTMASKS } from "./inputMask"
3
- import { stripEmojisForPaste, applyEmojiMask } from "../utilities/emojiMask"
4
3
 
5
4
  export default class PbTextInput extends PbEnhancedElement {
6
5
  static get selector() {
7
- return '[data-pb-input-mask="true"], [data-pb-emoji-mask="true"]';
6
+ return '[data-pb-input-mask="true"]';
8
7
  }
9
8
 
10
9
  connect() {
11
10
  this.handleInput = this.handleInput.bind(this);
12
- this.handlePaste = this.handlePaste.bind(this);
13
11
  this.element.addEventListener("input", this.handleInput);
14
- this.element.addEventListener("paste", this.handlePaste);
15
12
  this.handleInput();
16
13
  }
17
14
 
18
15
  disconnect() {
19
16
  this.element.removeEventListener("input", this.handleInput);
20
- this.element.removeEventListener("paste", this.handlePaste);
21
17
  }
22
18
 
23
- hasEmojiMask() {
24
- return this.element.dataset.pbEmojiMask === "true";
25
- }
26
-
27
- handlePaste(event) {
28
- if (!this.hasEmojiMask()) return;
29
-
30
- const pastedText = event.clipboardData.getData('text');
31
- const filteredText = stripEmojisForPaste(pastedText);
32
-
33
- if (pastedText !== filteredText) {
34
- event.preventDefault();
35
- const input = this.element;
36
- const start = input.selectionStart || 0;
37
- const end = input.selectionEnd || 0;
38
- const currentValue = input.value;
39
- const newValue = currentValue.slice(0, start) + filteredText + currentValue.slice(end);
40
- const newCursor = start + filteredText.length;
41
-
42
- input.value = newValue;
43
- input.selectionStart = input.selectionEnd = newCursor;
44
-
45
- // Continue to handleInput for mask processing, emoji filtering handled above
46
- this.handleInput({ skipEmojiFilter: true });
47
- }
48
- }
49
-
50
- handleInput({ skipEmojiFilter = false } = {}) {
51
- const cursorPosition = this.element.selectionStart;
52
- let baseValue = this.element.value;
53
-
54
- // Apply emoji mask if enabled (skip if already filtered in paste handler)
55
- if (this.hasEmojiMask() && !skipEmojiFilter) {
56
- const result = applyEmojiMask(this.element);
57
- baseValue = result.value;
58
- }
59
-
19
+ handleInput() {
60
20
  const maskType = this.element.getAttribute("mask");
61
- let formattedValue = baseValue;
21
+ const cursorPosition = this.element.selectionStart;
22
+ const rawValue = this.element.value;
23
+ let formattedValue = rawValue;
62
24
 
63
25
  const maskKey = {
64
26
  currency: 'currency',
@@ -70,14 +32,13 @@ export default class PbTextInput extends PbEnhancedElement {
70
32
  }[maskType];
71
33
 
72
34
  if (maskKey && INPUTMASKS[maskKey]) {
73
- formattedValue = INPUTMASKS[maskKey].format(baseValue);
35
+ formattedValue = INPUTMASKS[maskKey].format(rawValue);
74
36
  }
75
37
 
76
38
  const sanitizedInput = this.element
77
39
  .closest(".text_input_wrapper")
78
40
  ?.querySelector('[data="sanitized-pb-input"]');
79
41
 
80
- // Ensure sanitized input uses the already filtered value
81
42
  if (sanitizedInput) {
82
43
  switch (maskType) {
83
44
  case "ssn":
@@ -94,10 +55,8 @@ export default class PbTextInput extends PbEnhancedElement {
94
55
  }
95
56
  }
96
57
 
97
- if (maskType) {
98
- this.element.value = formattedValue;
99
- setCursorPosition(this.element, cursorPosition, baseValue, formattedValue);
100
- }
58
+ this.element.value = formattedValue;
59
+ setCursorPosition(this.element, cursorPosition, rawValue, formattedValue);
101
60
  }
102
61
  }
103
62
 
@@ -18,8 +18,6 @@ module Playbook
18
18
  prop :autocomplete, default: true
19
19
  prop :disabled, type: Playbook::Props::Boolean,
20
20
  default: false
21
- prop :emoji_mask, type: Playbook::Props::Boolean,
22
- default: false
23
21
  prop :error
24
22
  prop :inline, type: Playbook::Props::Boolean,
25
23
  default: false
@@ -119,9 +117,7 @@ module Playbook
119
117
  def validation_data
120
118
  fields = input_options.dig(:data) || {}
121
119
  fields[:message] = validation_message unless validation_message.blank?
122
- fields[:pb_input_mask] = true if mask
123
- fields[:pb_emoji_mask] = true if emoji_mask
124
- fields
120
+ mask ? fields.merge(pb_input_mask: true) : fields
125
121
  end
126
122
 
127
123
  def error_class
@@ -360,56 +360,3 @@ test('renders required indicator asterisk when requiredIndicator is true', () =>
360
360
  expect(label).toBeInTheDocument()
361
361
  expect(kit).toHaveTextContent('*')
362
362
  })
363
-
364
- const TextInputEmojiMask = (props) => {
365
- const [value, setValue] = useState('')
366
- const handleOnChange = ({ target }) => {
367
- setValue(target.value)
368
- }
369
-
370
- return (
371
- <TextInput
372
- emojiMask
373
- onChange={handleOnChange}
374
- value={value}
375
- {...props}
376
- />
377
- )
378
- }
379
-
380
- test('removes emoji characters when emojiMask is enabled', () => {
381
- render(
382
- <TextInputEmojiMask
383
- data={{ testid: testId }}
384
- />
385
- )
386
-
387
- const kit = screen.getByTestId(testId)
388
- const input = within(kit).getByRole('textbox')
389
-
390
- fireEvent.change(input, { target: { value: 'Hello 👋 World 🌍' } })
391
- expect(input.value).toBe('Hello World ')
392
-
393
- fireEvent.change(input, { target: { value: '😀😂🎉' } })
394
- expect(input.value).toBe('')
395
-
396
- fireEvent.change(input, { target: { value: 'Hello World' } })
397
- expect(input.value).toBe('Hello World')
398
- })
399
-
400
- test('allows accented characters when emojiMask is enabled', () => {
401
- render(
402
- <TextInputEmojiMask
403
- data={{ testid: testId }}
404
- />
405
- )
406
-
407
- const kit = screen.getByTestId(testId)
408
- const input = within(kit).getByRole('textbox')
409
-
410
- fireEvent.change(input, { target: { value: 'Café résumé naïve' } })
411
- expect(input.value).toBe('Café résumé naïve')
412
-
413
- fireEvent.change(input, { target: { value: 'àëǒüñ' } })
414
- expect(input.value).toBe('àëǒüñ')
415
- })
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable react-hooks/rules-of-hooks */
2
2
 
3
- import React, { forwardRef, useEffect, useRef, ChangeEvent, ClipboardEvent } from 'react'
3
+ import React, { forwardRef, useEffect, useRef } from 'react'
4
4
  import classnames from 'classnames'
5
5
 
6
6
  import PbTextarea from '.'
@@ -14,8 +14,6 @@ import Caption from '../pb_caption/_caption'
14
14
  import Flex from '../pb_flex/_flex'
15
15
  import FlexItem from '../pb_flex/_flex_item'
16
16
 
17
- import { stripEmojisForPaste, applyEmojiMask } from '../utilities/emojiMask'
18
-
19
17
  type TextareaProps = {
20
18
  aria?: {[key: string]: string},
21
19
  characterCount?: string,
@@ -23,7 +21,6 @@ type TextareaProps = {
23
21
  children?: React.ReactChild[],
24
22
  data?: {[key: string]: string},
25
23
  disabled?: boolean,
26
- emojiMask?: boolean,
27
24
  error?: string,
28
25
  htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
29
26
  id?: string,
@@ -48,7 +45,6 @@ const Textarea = ({
48
45
  children,
49
46
  data = {},
50
47
  disabled,
51
- emojiMask = false,
52
48
  htmlOptions = {},
53
49
  inline = false,
54
50
  resize = 'none',
@@ -71,37 +67,6 @@ const Textarea = ({
71
67
  }
72
68
  })
73
69
 
74
- const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
75
- // Apply emoji mask if enabled using centralized helper
76
- if (emojiMask) {
77
- applyEmojiMask(e.target)
78
- }
79
- onChange(e)
80
- }
81
-
82
- // Handle paste event for emoji mask - updates textarea value, cursor position, and calls onChange
83
- const handlePaste = (e: ClipboardEvent<HTMLTextAreaElement>) => {
84
- if (emojiMask) {
85
- const pastedText = e.clipboardData.getData('text')
86
- const filteredText = stripEmojisForPaste(pastedText)
87
-
88
- if (pastedText !== filteredText) {
89
- e.preventDefault()
90
- const textarea = e.currentTarget
91
- const start = textarea.selectionStart || 0
92
- const end = textarea.selectionEnd || 0
93
- const currentValue = textarea.value
94
- const newValue = currentValue.slice(0, start) + filteredText + currentValue.slice(end)
95
- const newCursorPosition = start + filteredText.length
96
-
97
- textarea.value = newValue
98
- textarea.selectionStart = textarea.selectionEnd = newCursorPosition
99
-
100
- onChange({ ...e, target: textarea, currentTarget: textarea } as unknown as ChangeEvent<HTMLTextAreaElement>)
101
- }
102
- }
103
- }
104
-
105
70
  const errorClass = error ? 'error' : null
106
71
  const inlineClass = inline ? 'inline' : ''
107
72
  const resizeClass = `resize_${resize}`
@@ -129,8 +94,7 @@ const Textarea = ({
129
94
  <textarea
130
95
  disabled={disabled}
131
96
  name={name}
132
- onChange={emojiMask ? handleChange : onChange}
133
- onPaste={emojiMask ? handlePaste : undefined}
97
+ onChange={onChange}
134
98
  placeholder={placeholder}
135
99
  ref={ref}
136
100
  required={required}
@@ -7,7 +7,6 @@ examples:
7
7
  - textarea_error: Textarea w/ Error
8
8
  - textarea_character_counter: Character Counter
9
9
  - textarea_inline: Inline
10
- - textarea_emoji_mask: Emoji Mask
11
10
 
12
11
  react:
13
12
  - textarea_default: Default
@@ -16,7 +15,6 @@ examples:
16
15
  - textarea_error: Textarea w/ Error
17
16
  - textarea_character_counter: Character Counter
18
17
  - textarea_inline: Inline
19
- - textarea_emoji_mask: Emoji Mask
20
18
 
21
19
  swift:
22
20
  - textarea_default_swift: Default
@@ -4,4 +4,3 @@ export { default as TextareaCustom } from './_textarea_custom.jsx'
4
4
  export { default as TextareaError } from './_textarea_error.jsx'
5
5
  export { default as TextareaCharacterCounter } from './_textarea_character_counter.jsx'
6
6
  export { default as TextareaInline } from './_textarea_inline.jsx'
7
- export { default as TextareaEmojiMask } from './_textarea_emoji_mask.jsx'
@@ -1,76 +1,19 @@
1
1
  import PbEnhancedElement from '../pb_enhanced_element'
2
- import { stripEmojisForPaste, applyEmojiMask } from '../utilities/emojiMask'
3
2
 
4
3
  export default class PbTextarea extends PbEnhancedElement {
5
4
  style: {[key: string]: string}
6
5
  scrollHeight: string
7
- private skipNextEmojiFilter = false
8
-
9
6
  static get selector(): string {
10
- return '.resize_auto textarea, [data-pb-emoji-mask="true"]'
11
- }
12
-
13
- hasEmojiMask(): boolean {
14
- return (this.element as HTMLElement).dataset.pbEmojiMask === "true"
7
+ return '.resize_auto textarea'
15
8
  }
16
9
 
17
10
  onInput(): void {
18
- if ((this.element as HTMLElement).closest('.resize_auto')) {
19
- this.style.height = 'auto'
20
- this.style.height = (this.scrollHeight) + 'px'
21
- }
22
- }
23
-
24
- handleEmojiInput = (): void => {
25
- if (!this.hasEmojiMask()) return
26
-
27
- if (this.skipNextEmojiFilter) {
28
- this.skipNextEmojiFilter = false
29
- return
30
- }
31
-
32
- applyEmojiMask(this.element as HTMLTextAreaElement)
33
- }
34
-
35
- handleEmojiPaste = (event: ClipboardEvent): void => {
36
- if (!this.hasEmojiMask()) return
37
-
38
- const pastedText = event.clipboardData?.getData('text') || ''
39
- const filteredText = stripEmojisForPaste(pastedText)
40
-
41
- if (pastedText !== filteredText) {
42
- event.preventDefault()
43
- const textarea = this.element as HTMLTextAreaElement
44
- const start = textarea.selectionStart || 0
45
- const end = textarea.selectionEnd || 0
46
- const currentValue = textarea.value
47
- const newValue = currentValue.slice(0, start) + filteredText + currentValue.slice(end)
48
- const newCursor = start + filteredText.length
49
-
50
- textarea.value = newValue
51
- textarea.selectionStart = textarea.selectionEnd = newCursor
52
-
53
- this.skipNextEmojiFilter = true
54
-
55
- textarea.dispatchEvent(new Event('input', { bubbles: true }))
56
- }
11
+ this.style.height = 'auto'
12
+ this.style.height = (this.scrollHeight) + 'px'
57
13
  }
58
14
 
59
15
  connect(): void {
60
- if ((this.element as HTMLElement).closest('.resize_auto')) {
61
- this.element.setAttribute('style', 'height:' + (this.element as HTMLTextAreaElement).scrollHeight + 'px;overflow-y:hidden;')
62
- this.element.addEventListener('input', this.onInput, false)
63
- }
64
-
65
- if (this.hasEmojiMask()) {
66
- this.element.addEventListener('input', this.handleEmojiInput, false)
67
- this.element.addEventListener('paste', this.handleEmojiPaste as EventListener, false)
68
- }
69
- }
70
-
71
- disconnect(): void {
72
- this.element.removeEventListener('input', this.onInput, false)
73
- this.element.removeEventListener('input', this.handleEmojiInput, false)
74
- this.element.removeEventListener('paste', this.handleEmojiPaste as EventListener, false)
16
+ this.element.setAttribute('style', 'height:' + (this.element.scrollHeight) + 'px;overflow-y:hidden;')
17
+ this.element.addEventListener('input', this.onInput, false)
75
18
  }
76
19
  }
@@ -11,7 +11,6 @@
11
11
  <%= text_area(
12
12
  :object,
13
13
  :method,
14
- :data => object.textarea_options[:data],
15
14
  :max_characters => object.max_characters,
16
15
  :name => object.name,
17
16
  :onkeyup => object.onkeyup,
@@ -3,8 +3,6 @@
3
3
  module Playbook
4
4
  module PbTextarea
5
5
  class Textarea < Playbook::KitBase
6
- prop :emoji_mask, type: Playbook::Props::Boolean,
7
- default: false
8
6
  prop :error
9
7
  prop :inline, type: Playbook::Props::Boolean,
10
8
  default: false
@@ -30,12 +28,6 @@ module Playbook
30
28
  max_characters && character_count ? "#{character_count} / #{max_characters}" : character_count
31
29
  end
32
30
 
33
- def textarea_options
34
- {
35
- data: emoji_mask ? { pb_emoji_mask: true } : {},
36
- }
37
- end
38
-
39
31
  private
40
32
 
41
33
  def error_class