@remember-web/primitive 0.2.8 → 0.2.10

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 (58) hide show
  1. package/dist/src/Chips/Chip/const.cjs.js +107 -0
  2. package/dist/src/Chips/Chip/const.cjs.js.map +1 -0
  3. package/dist/src/Chips/Chip/const.d.ts +15 -0
  4. package/dist/src/Chips/Chip/const.d.ts.map +1 -0
  5. package/dist/src/Chips/Chip/const.esm.js +104 -0
  6. package/dist/src/Chips/Chip/const.esm.js.map +1 -0
  7. package/dist/src/Chips/Chip/index.cjs.js +57 -0
  8. package/dist/src/Chips/Chip/index.cjs.js.map +1 -0
  9. package/dist/src/Chips/Chip/index.d.ts +4 -0
  10. package/dist/src/Chips/Chip/index.d.ts.map +1 -0
  11. package/dist/src/Chips/Chip/index.esm.js +50 -0
  12. package/dist/src/Chips/Chip/index.esm.js.map +1 -0
  13. package/dist/src/Chips/Chip/styles.cjs.js +46 -0
  14. package/dist/src/Chips/Chip/styles.cjs.js.map +1 -0
  15. package/dist/src/Chips/Chip/styles.d.ts +5 -0
  16. package/dist/src/Chips/Chip/styles.d.ts.map +1 -0
  17. package/dist/src/Chips/Chip/styles.esm.js +36 -0
  18. package/dist/src/Chips/Chip/styles.esm.js.map +1 -0
  19. package/dist/src/Chips/Chip/typeGuard.cjs.js +31 -0
  20. package/dist/src/Chips/Chip/typeGuard.cjs.js.map +1 -0
  21. package/dist/src/Chips/Chip/typeGuard.d.ts +3 -0
  22. package/dist/src/Chips/Chip/typeGuard.d.ts.map +1 -0
  23. package/dist/src/Chips/Chip/typeGuard.esm.js +29 -0
  24. package/dist/src/Chips/Chip/typeGuard.esm.js.map +1 -0
  25. package/dist/src/Chips/Chip/types.d.ts +43 -0
  26. package/dist/src/Chips/Chip/types.d.ts.map +1 -0
  27. package/dist/src/Chips/index.d.ts +2 -0
  28. package/dist/src/Chips/index.d.ts.map +1 -0
  29. package/dist/src/Inputs/TextInput/index.cjs.js +8 -2
  30. package/dist/src/Inputs/TextInput/index.cjs.js.map +1 -1
  31. package/dist/src/Inputs/TextInput/index.d.ts.map +1 -1
  32. package/dist/src/Inputs/TextInput/index.esm.js +8 -2
  33. package/dist/src/Inputs/TextInput/index.esm.js.map +1 -1
  34. package/dist/src/Inputs/TextInput/styles.cjs.js +2 -2
  35. package/dist/src/Inputs/TextInput/styles.cjs.js.map +1 -1
  36. package/dist/src/Inputs/TextInput/styles.d.ts +1 -1
  37. package/dist/src/Inputs/TextInput/styles.esm.js +2 -2
  38. package/dist/src/Inputs/TextInput/styles.esm.js.map +1 -1
  39. package/dist/src/index.cjs.js +2 -0
  40. package/dist/src/index.cjs.js.map +1 -1
  41. package/dist/src/index.d.ts +1 -0
  42. package/dist/src/index.d.ts.map +1 -1
  43. package/dist/src/index.esm.js +1 -0
  44. package/dist/src/index.esm.js.map +1 -1
  45. package/dist/src/stories/common.styles.d.ts +2 -1
  46. package/dist/src/stories/common.styles.d.ts.map +1 -1
  47. package/package.json +2 -2
  48. package/src/Chips/Chip/Chip.stories.tsx +138 -0
  49. package/src/Chips/Chip/const.ts +115 -0
  50. package/src/Chips/Chip/index.tsx +51 -0
  51. package/src/Chips/Chip/styles.ts +80 -0
  52. package/src/Chips/Chip/typeGuard.ts +48 -0
  53. package/src/Chips/Chip/types.ts +61 -0
  54. package/src/Chips/index.ts +1 -0
  55. package/src/Inputs/TextInput/index.tsx +9 -2
  56. package/src/Inputs/TextInput/styles.ts +3 -3
  57. package/src/index.ts +1 -0
  58. package/src/stories/common.styles.tsx +10 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typeGuard.esm.js","sources":["../../../../src/Chips/Chip/typeGuard.ts"],"sourcesContent":["import type { ChipProps, ChipSize, ChipVariant } from './types';\n\nexport function ensureValidChipProps(props: ChipProps): props is ChipProps {\n if (props.clickable === false && 'selected' in props) {\n throw new Error(\n '오류: \"clickable\"이 false일 때는 \"selected\" 속성을 사용할 수 없습니다. ' +\n '선택 가능한 Chip을 만들려면 \"clickable\"을 true로 설정하세요.'\n );\n }\n\n if (props.onDelete === undefined && 'deleteIcon' in props) {\n throw new Error(\n '오류: \"onDelete\" 함수 없이 \"deleteIcon\"을 사용할 수 없습니다. ' +\n '\"deleteIcon\"을 사용하려면 \"onDelete\" 함수를 함께 사용해야 합니다.'\n );\n }\n\n if (!props.children) {\n throw new Error(\n '오류: Chip 컴포넌트에는 반드시 children이 있어야 합니다. '\n );\n }\n\n if (!props.size) {\n throw new Error('오류: Chip 컴포넌트에는 반드시 size가 있어야 합니다. ');\n }\n\n if (!props.variant) {\n throw new Error('오류: Chip 컴포넌트에는 반드시 variant가 있어야 합니다. ');\n }\n\n const validSizes: ChipSize[] = ['small', 'medium'];\n if (props.size && !validSizes.includes(props.size)) {\n throw new Error(\n `오류: 올바르지 않은 size 값입니다: \"${props.size}\". ` +\n `유효한 size 값은 다음과 같습니다: ${validSizes.join(', ')}.`\n );\n }\n\n const validVariants: ChipVariant[] = ['filled', 'outline', 'dashedLine'];\n if (props.variant && !validVariants.includes(props.variant)) {\n throw new Error(\n `오류: 올바르지 않은 variant 값입니다: \"${props.variant}\". ` +\n `유효한 variant 값은 다음과 같습니다: ${validVariants.join(', ')}.`\n );\n }\n return true;\n}\n"],"names":["ensureValidChipProps","props","clickable","Error","onDelete","undefined","children","size","variant","validSizes","includes","concat","join","validVariants"],"mappings":"AAEO,SAASA,oBAAoBA,CAACC,KAAgB,EAAsB;EACzE,IAAIA,KAAK,CAACC,SAAS,KAAK,KAAK,IAAI,UAAU,IAAID,KAAK,EAAE;AACpD,IAAA,MAAM,IAAIE,KAAK,CACb,wDAAwD,GACtD,6CACJ,CAAC,CAAA;AACH,GAAA;EAEA,IAAIF,KAAK,CAACG,QAAQ,KAAKC,SAAS,IAAI,YAAY,IAAIJ,KAAK,EAAE;AACzD,IAAA,MAAM,IAAIE,KAAK,CACb,iDAAiD,GAC/C,iDACJ,CAAC,CAAA;AACH,GAAA;AAEA,EAAA,IAAI,CAACF,KAAK,CAACK,QAAQ,EAAE;AACnB,IAAA,MAAM,IAAIH,KAAK,CACb,yCACF,CAAC,CAAA;AACH,GAAA;AAEA,EAAA,IAAI,CAACF,KAAK,CAACM,IAAI,EAAE;AACf,IAAA,MAAM,IAAIJ,KAAK,CAAC,qCAAqC,CAAC,CAAA;AACxD,GAAA;AAEA,EAAA,IAAI,CAACF,KAAK,CAACO,OAAO,EAAE;AAClB,IAAA,MAAM,IAAIL,KAAK,CAAC,wCAAwC,CAAC,CAAA;AAC3D,GAAA;AAEA,EAAA,IAAMM,UAAsB,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;AAClD,EAAA,IAAIR,KAAK,CAACM,IAAI,IAAI,CAACE,UAAU,CAACC,QAAQ,CAACT,KAAK,CAACM,IAAI,CAAC,EAAE;AAClD,IAAA,MAAM,IAAIJ,KAAK,CACb,wFAAAQ,MAAA,CAA2BV,KAAK,CAACM,IAAI,iGAAAI,MAAA,CACVF,UAAU,CAACG,IAAI,CAAC,IAAI,CAAC,MAClD,CAAC,CAAA;AACH,GAAA;EAEA,IAAMC,aAA4B,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,YAAY,CAAC,CAAA;AACxE,EAAA,IAAIZ,KAAK,CAACO,OAAO,IAAI,CAACK,aAAa,CAACH,QAAQ,CAACT,KAAK,CAACO,OAAO,CAAC,EAAE;AAC3D,IAAA,MAAM,IAAIL,KAAK,CACb,2FAAAQ,MAAA,CAA8BV,KAAK,CAACO,OAAO,oGAAAG,MAAA,CACbE,aAAa,CAACD,IAAI,CAAC,IAAI,CAAC,MACxD,CAAC,CAAA;AACH,GAAA;AACA,EAAA,OAAO,IAAI,CAAA;AACb;;;;"}
@@ -0,0 +1,43 @@
1
+ import type { ComponentProps } from 'react';
2
+ export type ChipSize = 'small' | 'medium';
3
+ export type ChipVariant = 'filled' | 'outline' | 'dashedLine';
4
+ type ClickableProps = {
5
+ clickable?: true;
6
+ selected?: boolean;
7
+ } | {
8
+ clickable: false;
9
+ selected?: never;
10
+ };
11
+ type DeleteProps = {
12
+ onDelete: VoidFunction;
13
+ deleteIcon?: React.ReactNode;
14
+ } | {
15
+ onDelete?: never;
16
+ deleteIcon?: never;
17
+ };
18
+ type BaseChipProps = {
19
+ size: ChipSize;
20
+ variant: ChipVariant;
21
+ children: React.ReactNode;
22
+ leftIcon?: React.ReactNode;
23
+ disabled?: boolean;
24
+ };
25
+ export type ChipProps = BaseChipProps & ClickableProps & DeleteProps & ComponentProps<'div'>;
26
+ export type ChipState = 'default' | 'hover' | 'disabled' | 'selected';
27
+ export type ChipStyleProps = {
28
+ $size: ChipSize;
29
+ $variant: ChipVariant;
30
+ $clickable: boolean;
31
+ $selected: boolean;
32
+ };
33
+ interface ChipStateStyle {
34
+ backgroundColor: string;
35
+ color: string;
36
+ leftIconColor: string;
37
+ deleteButtonColor: string;
38
+ border?: string;
39
+ }
40
+ type ChipStateStyles = Record<ChipState, ChipStateStyle>;
41
+ export type ChipVariantStyleMap = Record<ChipVariant, ChipStateStyles>;
42
+ export {};
43
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/Chips/Chip/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAG5C,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE1C,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,CAAC;AAE9D,KAAK,cAAc,GACf;IACE,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GACD;IACE,SAAS,EAAE,KAAK,CAAC;IACjB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB,CAAC;AAEN,KAAK,WAAW,GACZ;IACE,QAAQ,EAAE,YAAY,CAAC;IACvB,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B,GACD;IACE,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,UAAU,CAAC,EAAE,KAAK,CAAC;CACpB,CAAC;AAEN,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,aAAa,GACnC,cAAc,GACd,WAAW,GACX,cAAc,CAAC,KAAK,CAAC,CAAC;AAGxB,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC;AAEtE,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,QAAQ,CAAC;IAChB,QAAQ,EAAE,WAAW,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,UAAU,cAAc;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,eAAe,GAAG,MAAM,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;AAEzD,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './Chip';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/Chips/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC"}
@@ -36,6 +36,12 @@ var TextInput = function TextInput(_ref, ref) {
36
36
  isVisiblePassword = _useState2[0],
37
37
  setIsVisiblePassword = _useState2[1];
38
38
  var isForceVisibleInput = props.type === 'password' && props.hasTogglePasswordVisibilityButton && isVisiblePassword;
39
+
40
+ // NOTE: InputInner 컴포넌트에 전달되는 input native 속성에 커스텀 props인 hasTogglePasswordVisibilityButton가 전달되지 않도록 하는 처리
41
+ // type === 'password' 일 때에 hasTogglePasswordVisibilityButton 속성이 존재할 수 있음.
42
+ var inputInnerProps = _objectSpread(_objectSpread({}, props), {}, {
43
+ hasTogglePasswordVisibilityButton: undefined
44
+ });
39
45
  return /*#__PURE__*/jsxRuntime.jsxs(styles.InputWrapper, {
40
46
  $width: width,
41
47
  children: [label && /*#__PURE__*/jsxRuntime.jsxs(styles.InputLabel, {
@@ -46,7 +52,7 @@ var TextInput = function TextInput(_ref, ref) {
46
52
  })]
47
53
  }), /*#__PURE__*/jsxRuntime.jsxs(styles.InputContainer, {
48
54
  disabled: disabled,
49
- hasError: !!errorMessage,
55
+ $hasError: !!errorMessage,
50
56
  className: className,
51
57
  children: [leftElement && /*#__PURE__*/jsxRuntime.jsx(styles.InputDecorator, {
52
58
  children: leftElement
@@ -54,7 +60,7 @@ var TextInput = function TextInput(_ref, ref) {
54
60
  disabled: disabled,
55
61
  id: inputId,
56
62
  "aria-labelledby": label ? labelId : undefined
57
- }, props), {}, {
63
+ }, inputInnerProps), {}, {
58
64
  type: isForceVisibleInput ? 'text' : props.type || 'text',
59
65
  ref: ref
60
66
  })), hintText && /*#__PURE__*/jsxRuntime.jsx(styles.InputHintText, {
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../../../../src/Inputs/TextInput/index.tsx"],"sourcesContent":["'use client';\n\nimport { IconHidden, IconVisible } from '@remember-web/icon';\nimport type { ForwardRefRenderFunction } from 'react';\nimport { forwardRef, useId, useState } from 'react';\n\nimport {\n InputContainer,\n InputDecorator,\n InputError,\n InputHintText,\n InputInner,\n InputLabel,\n InputTogglePasswordVisibilityButton,\n InputWrapper,\n} from './styles';\nimport type { InputProps } from './types';\n\nconst TextInput: ForwardRefRenderFunction<HTMLInputElement, InputProps> = (\n {\n className,\n label,\n leftElement,\n rightElement,\n disabled,\n hintText,\n hintTextColor,\n errorMessage,\n width,\n ...props\n },\n ref\n) => {\n const inputId = useId();\n const labelId = useId();\n const [isVisiblePassword, setIsVisiblePassword] = useState(false);\n const isForceVisibleInput =\n props.type === 'password' &&\n props.hasTogglePasswordVisibilityButton &&\n isVisiblePassword;\n\n return (\n <InputWrapper $width={width}>\n {label && (\n <InputLabel id={labelId} htmlFor={inputId}>\n {label}\n {props.required && <mark>*</mark>}\n </InputLabel>\n )}\n <InputContainer\n disabled={disabled}\n hasError={!!errorMessage}\n className={className}\n >\n {leftElement && <InputDecorator>{leftElement}</InputDecorator>}\n <InputInner\n disabled={disabled}\n id={inputId}\n aria-labelledby={label ? labelId : undefined}\n {...props}\n type={isForceVisibleInput ? 'text' : props.type || 'text'}\n ref={ref}\n />\n {hintText && (\n <InputHintText textColor={hintTextColor}>{hintText}</InputHintText>\n )}\n {props.type === 'password' &&\n props.hasTogglePasswordVisibilityButton && (\n <TogglePasswordVisibilityButton\n value={isVisiblePassword}\n onChange={setIsVisiblePassword}\n />\n )}\n {rightElement && <InputDecorator>{rightElement}</InputDecorator>}\n </InputContainer>\n {errorMessage && <InputError>{errorMessage}</InputError>}\n </InputWrapper>\n );\n};\n\nconst TogglePasswordVisibilityButton = ({\n value,\n onChange,\n}: {\n value: boolean;\n onChange: (value: boolean) => void;\n}) => (\n <InputTogglePasswordVisibilityButton\n type=\"button\"\n role=\"switch\"\n aria-checked={value ? 'true' : 'false'}\n aria-label=\"비밀번호 표시\"\n onClick={() => {\n onChange(!value);\n }}\n >\n {value ? <IconHidden size=\"small\" /> : <IconVisible size=\"small\" />}\n </InputTogglePasswordVisibilityButton>\n);\n\nexport default forwardRef(TextInput);\n"],"names":["props","isVisiblePassword","setIsVisiblePassword","$width","children","id","htmlFor","disabled","className","ref","textColor","value","onChange","type","role","size"],"mappings":";;;;;;;;;;;;;;;;;AAAa;AAAA;AAAA;AAkBb;AAcK;;;;;;;;;AAHEA;AAIL;AACA;AACA;;AAAOC;AAAmBC;AAC1B;;AAMgBC;AAAcC;AAEZC;AAAaC;AAAiBF;AAErBA;AAAO;AAAO;AAInCG;;AAEAC;AAAqBJ;AAEUA;;AAE7BG;AACAF;;AAC6C;;AAG7CI;AAAS;AAGMC;AAAyBN;AAAU;AAK9CO;AACAC;AAA+B;AAGLR;AAAc;AAAkB;AAEtCA;AAAc;AAAc;AAG9D;AAEA;AAAoC;;;AAQhCS;AACAC;AACA;AACA;;;;AAGEV;AAEmBW;AAAY;AAAmBA;;AAAe;AAC/B;AAGxC;;"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../../../../src/Inputs/TextInput/index.tsx"],"sourcesContent":["'use client';\n\nimport { IconHidden, IconVisible } from '@remember-web/icon';\nimport type { ForwardRefRenderFunction } from 'react';\nimport { forwardRef, useId, useState } from 'react';\n\nimport {\n InputContainer,\n InputDecorator,\n InputError,\n InputHintText,\n InputInner,\n InputLabel,\n InputTogglePasswordVisibilityButton,\n InputWrapper,\n} from './styles';\nimport type { InputProps } from './types';\n\nconst TextInput: ForwardRefRenderFunction<HTMLInputElement, InputProps> = (\n {\n className,\n label,\n leftElement,\n rightElement,\n disabled,\n hintText,\n hintTextColor,\n errorMessage,\n width,\n ...props\n },\n ref\n) => {\n const inputId = useId();\n const labelId = useId();\n const [isVisiblePassword, setIsVisiblePassword] = useState(false);\n const isForceVisibleInput =\n props.type === 'password' &&\n props.hasTogglePasswordVisibilityButton &&\n isVisiblePassword;\n\n // NOTE: InputInner 컴포넌트에 전달되는 input native 속성에 커스텀 props인 hasTogglePasswordVisibilityButton가 전달되지 않도록 하는 처리\n // type === 'password' 일 때에 hasTogglePasswordVisibilityButton 속성이 존재할 수 있음.\n const inputInnerProps = {\n ...props,\n hasTogglePasswordVisibilityButton: undefined,\n };\n\n return (\n <InputWrapper $width={width}>\n {label && (\n <InputLabel id={labelId} htmlFor={inputId}>\n {label}\n {props.required && <mark>*</mark>}\n </InputLabel>\n )}\n <InputContainer\n disabled={disabled}\n $hasError={!!errorMessage}\n className={className}\n >\n {leftElement && <InputDecorator>{leftElement}</InputDecorator>}\n <InputInner\n disabled={disabled}\n id={inputId}\n aria-labelledby={label ? labelId : undefined}\n {...inputInnerProps}\n type={isForceVisibleInput ? 'text' : props.type || 'text'}\n ref={ref}\n />\n {hintText && (\n <InputHintText textColor={hintTextColor}>{hintText}</InputHintText>\n )}\n {props.type === 'password' &&\n props.hasTogglePasswordVisibilityButton && (\n <TogglePasswordVisibilityButton\n value={isVisiblePassword}\n onChange={setIsVisiblePassword}\n />\n )}\n {rightElement && <InputDecorator>{rightElement}</InputDecorator>}\n </InputContainer>\n {errorMessage && <InputError>{errorMessage}</InputError>}\n </InputWrapper>\n );\n};\n\nconst TogglePasswordVisibilityButton = ({\n value,\n onChange,\n}: {\n value: boolean;\n onChange: (value: boolean) => void;\n}) => (\n <InputTogglePasswordVisibilityButton\n type=\"button\"\n role=\"switch\"\n aria-checked={value ? 'true' : 'false'}\n aria-label=\"비밀번호 표시\"\n onClick={() => {\n onChange(!value);\n }}\n >\n {value ? <IconHidden size=\"small\" /> : <IconVisible size=\"small\" />}\n </InputTogglePasswordVisibilityButton>\n);\n\nexport default forwardRef(TextInput);\n"],"names":["props","isVisiblePassword","setIsVisiblePassword","hasTogglePasswordVisibilityButton","$width","children","id","htmlFor","disabled","className","ref","textColor","value","onChange","type","role","size"],"mappings":";;;;;;;;;;;;;;;;;AAAa;AAAA;AAAA;AAkBb;AAcK;;;;;;;;;AAHEA;AAIL;AACA;AACA;;AAAOC;AAAmBC;AAC1B;;AAKA;AACA;AACA;AAEEC;;;AAIcC;AAAcC;AAEZC;AAAaC;AAAiBF;AAErBA;AAAO;AAAO;AAInCG;;AAEAC;AAAqBJ;AAEUA;;AAE7BG;AACAF;;AAC6C;;AAG7CI;AAAS;AAGMC;AAAyBN;AAAU;AAK9CO;AACAC;AAA+B;AAGLR;AAAc;AAAkB;AAEtCA;AAAc;AAAc;AAG9D;AAEA;AAAoC;;;AAQhCS;AACAC;AACA;AACA;;;;AAGEV;AAEmBW;AAAY;AAAmBA;;AAAe;AAC/B;AAGxC;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/Inputs/TextInput/index.tsx"],"names":[],"mappings":";AAgBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;;AAoF1C,wBAAqC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/Inputs/TextInput/index.tsx"],"names":[],"mappings":";AAgBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;;AA2F1C,wBAAqC"}
@@ -28,6 +28,12 @@ var TextInput = function TextInput(_ref, ref) {
28
28
  isVisiblePassword = _useState2[0],
29
29
  setIsVisiblePassword = _useState2[1];
30
30
  var isForceVisibleInput = props.type === 'password' && props.hasTogglePasswordVisibilityButton && isVisiblePassword;
31
+
32
+ // NOTE: InputInner 컴포넌트에 전달되는 input native 속성에 커스텀 props인 hasTogglePasswordVisibilityButton가 전달되지 않도록 하는 처리
33
+ // type === 'password' 일 때에 hasTogglePasswordVisibilityButton 속성이 존재할 수 있음.
34
+ var inputInnerProps = _objectSpread(_objectSpread({}, props), {}, {
35
+ hasTogglePasswordVisibilityButton: undefined
36
+ });
31
37
  return /*#__PURE__*/jsxs(InputWrapper, {
32
38
  $width: width,
33
39
  children: [label && /*#__PURE__*/jsxs(InputLabel, {
@@ -38,7 +44,7 @@ var TextInput = function TextInput(_ref, ref) {
38
44
  })]
39
45
  }), /*#__PURE__*/jsxs(InputContainer, {
40
46
  disabled: disabled,
41
- hasError: !!errorMessage,
47
+ $hasError: !!errorMessage,
42
48
  className: className,
43
49
  children: [leftElement && /*#__PURE__*/jsx(InputDecorator, {
44
50
  children: leftElement
@@ -46,7 +52,7 @@ var TextInput = function TextInput(_ref, ref) {
46
52
  disabled: disabled,
47
53
  id: inputId,
48
54
  "aria-labelledby": label ? labelId : undefined
49
- }, props), {}, {
55
+ }, inputInnerProps), {}, {
50
56
  type: isForceVisibleInput ? 'text' : props.type || 'text',
51
57
  ref: ref
52
58
  })), hintText && /*#__PURE__*/jsx(InputHintText, {
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../../../../src/Inputs/TextInput/index.tsx"],"sourcesContent":["'use client';\n\nimport { IconHidden, IconVisible } from '@remember-web/icon';\nimport type { ForwardRefRenderFunction } from 'react';\nimport { forwardRef, useId, useState } from 'react';\n\nimport {\n InputContainer,\n InputDecorator,\n InputError,\n InputHintText,\n InputInner,\n InputLabel,\n InputTogglePasswordVisibilityButton,\n InputWrapper,\n} from './styles';\nimport type { InputProps } from './types';\n\nconst TextInput: ForwardRefRenderFunction<HTMLInputElement, InputProps> = (\n {\n className,\n label,\n leftElement,\n rightElement,\n disabled,\n hintText,\n hintTextColor,\n errorMessage,\n width,\n ...props\n },\n ref\n) => {\n const inputId = useId();\n const labelId = useId();\n const [isVisiblePassword, setIsVisiblePassword] = useState(false);\n const isForceVisibleInput =\n props.type === 'password' &&\n props.hasTogglePasswordVisibilityButton &&\n isVisiblePassword;\n\n return (\n <InputWrapper $width={width}>\n {label && (\n <InputLabel id={labelId} htmlFor={inputId}>\n {label}\n {props.required && <mark>*</mark>}\n </InputLabel>\n )}\n <InputContainer\n disabled={disabled}\n hasError={!!errorMessage}\n className={className}\n >\n {leftElement && <InputDecorator>{leftElement}</InputDecorator>}\n <InputInner\n disabled={disabled}\n id={inputId}\n aria-labelledby={label ? labelId : undefined}\n {...props}\n type={isForceVisibleInput ? 'text' : props.type || 'text'}\n ref={ref}\n />\n {hintText && (\n <InputHintText textColor={hintTextColor}>{hintText}</InputHintText>\n )}\n {props.type === 'password' &&\n props.hasTogglePasswordVisibilityButton && (\n <TogglePasswordVisibilityButton\n value={isVisiblePassword}\n onChange={setIsVisiblePassword}\n />\n )}\n {rightElement && <InputDecorator>{rightElement}</InputDecorator>}\n </InputContainer>\n {errorMessage && <InputError>{errorMessage}</InputError>}\n </InputWrapper>\n );\n};\n\nconst TogglePasswordVisibilityButton = ({\n value,\n onChange,\n}: {\n value: boolean;\n onChange: (value: boolean) => void;\n}) => (\n <InputTogglePasswordVisibilityButton\n type=\"button\"\n role=\"switch\"\n aria-checked={value ? 'true' : 'false'}\n aria-label=\"비밀번호 표시\"\n onClick={() => {\n onChange(!value);\n }}\n >\n {value ? <IconHidden size=\"small\" /> : <IconVisible size=\"small\" />}\n </InputTogglePasswordVisibilityButton>\n);\n\nexport default forwardRef(TextInput);\n"],"names":["props","isVisiblePassword","setIsVisiblePassword","$width","children","id","htmlFor","disabled","className","ref","textColor","value","onChange","type","role","size"],"mappings":";;;;;;;;;AAAa;AAAA;AAAA;AAkBb;AAcK;;;;;;;;;AAHEA;AAIL;AACA;AACA;;AAAOC;AAAmBC;AAC1B;;AAMgBC;AAAcC;AAEZC;AAAaC;AAAiBF;AAErBA;AAAO;AAAO;AAInCG;;AAEAC;AAAqBJ;AAEUA;;AAE7BG;AACAF;;AAC6C;;AAG7CI;AAAS;AAGMC;AAAyBN;AAAU;AAK9CO;AACAC;AAA+B;AAGLR;AAAc;AAAkB;AAEtCA;AAAc;AAAc;AAG9D;AAEA;AAAoC;;;AAQhCS;AACAC;AACA;AACA;;;;AAGEV;AAEmBW;AAAY;AAAmBA;;AAAe;AAC/B;AAGxC;;"}
1
+ {"version":3,"file":"index.esm.js","sources":["../../../../src/Inputs/TextInput/index.tsx"],"sourcesContent":["'use client';\n\nimport { IconHidden, IconVisible } from '@remember-web/icon';\nimport type { ForwardRefRenderFunction } from 'react';\nimport { forwardRef, useId, useState } from 'react';\n\nimport {\n InputContainer,\n InputDecorator,\n InputError,\n InputHintText,\n InputInner,\n InputLabel,\n InputTogglePasswordVisibilityButton,\n InputWrapper,\n} from './styles';\nimport type { InputProps } from './types';\n\nconst TextInput: ForwardRefRenderFunction<HTMLInputElement, InputProps> = (\n {\n className,\n label,\n leftElement,\n rightElement,\n disabled,\n hintText,\n hintTextColor,\n errorMessage,\n width,\n ...props\n },\n ref\n) => {\n const inputId = useId();\n const labelId = useId();\n const [isVisiblePassword, setIsVisiblePassword] = useState(false);\n const isForceVisibleInput =\n props.type === 'password' &&\n props.hasTogglePasswordVisibilityButton &&\n isVisiblePassword;\n\n // NOTE: InputInner 컴포넌트에 전달되는 input native 속성에 커스텀 props인 hasTogglePasswordVisibilityButton가 전달되지 않도록 하는 처리\n // type === 'password' 일 때에 hasTogglePasswordVisibilityButton 속성이 존재할 수 있음.\n const inputInnerProps = {\n ...props,\n hasTogglePasswordVisibilityButton: undefined,\n };\n\n return (\n <InputWrapper $width={width}>\n {label && (\n <InputLabel id={labelId} htmlFor={inputId}>\n {label}\n {props.required && <mark>*</mark>}\n </InputLabel>\n )}\n <InputContainer\n disabled={disabled}\n $hasError={!!errorMessage}\n className={className}\n >\n {leftElement && <InputDecorator>{leftElement}</InputDecorator>}\n <InputInner\n disabled={disabled}\n id={inputId}\n aria-labelledby={label ? labelId : undefined}\n {...inputInnerProps}\n type={isForceVisibleInput ? 'text' : props.type || 'text'}\n ref={ref}\n />\n {hintText && (\n <InputHintText textColor={hintTextColor}>{hintText}</InputHintText>\n )}\n {props.type === 'password' &&\n props.hasTogglePasswordVisibilityButton && (\n <TogglePasswordVisibilityButton\n value={isVisiblePassword}\n onChange={setIsVisiblePassword}\n />\n )}\n {rightElement && <InputDecorator>{rightElement}</InputDecorator>}\n </InputContainer>\n {errorMessage && <InputError>{errorMessage}</InputError>}\n </InputWrapper>\n );\n};\n\nconst TogglePasswordVisibilityButton = ({\n value,\n onChange,\n}: {\n value: boolean;\n onChange: (value: boolean) => void;\n}) => (\n <InputTogglePasswordVisibilityButton\n type=\"button\"\n role=\"switch\"\n aria-checked={value ? 'true' : 'false'}\n aria-label=\"비밀번호 표시\"\n onClick={() => {\n onChange(!value);\n }}\n >\n {value ? <IconHidden size=\"small\" /> : <IconVisible size=\"small\" />}\n </InputTogglePasswordVisibilityButton>\n);\n\nexport default forwardRef(TextInput);\n"],"names":["props","isVisiblePassword","setIsVisiblePassword","hasTogglePasswordVisibilityButton","$width","children","id","htmlFor","disabled","className","ref","textColor","value","onChange","type","role","size"],"mappings":";;;;;;;;;AAAa;AAAA;AAAA;AAkBb;AAcK;;;;;;;;;AAHEA;AAIL;AACA;AACA;;AAAOC;AAAmBC;AAC1B;;AAKA;AACA;AACA;AAEEC;;;AAIcC;AAAcC;AAEZC;AAAaC;AAAiBF;AAErBA;AAAO;AAAO;AAInCG;;AAEAC;AAAqBJ;AAEUA;;AAE7BG;AACAF;;AAC6C;;AAG7CI;AAAS;AAGMC;AAAyBN;AAAU;AAK9CO;AACAC;AAA+B;AAGLR;AAAc;AAAkB;AAEtCA;AAAc;AAAc;AAG9D;AAEA;AAAoC;;;AAQhCS;AACAC;AACA;AACA;;;;AAGEV;AAEmBW;AAAY;AAAmBA;;AAAe;AAC/B;AAGxC;;"}
@@ -17,9 +17,9 @@ var InputWrapper = styled__default.default.div(_templateObject || (_templateObje
17
17
  return $width && styled.css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral__default.default(["\n width: ", ";\n "])), shared.formatUnit($width));
18
18
  });
19
19
  var InputContainer = styled__default.default.div(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral__default.default(["\n display: flex;\n align-items: center;\n border: 1px solid ", ";\n border-radius: 4px;\n padding: 0 12px;\n gap: 8px;\n\n transition:\n border-color 0.2s,\n background-color 0.2s;\n\n ", "\n"])), mixin.contents300, function (_ref2) {
20
- var hasError = _ref2.hasError,
20
+ var $hasError = _ref2.$hasError,
21
21
  disabled = _ref2.disabled;
22
- return [hasError ? styled.css(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral__default.default(["\n border-color: ", ";\n "])), mixin.roleRed) : styled.css(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral__default.default(["\n &:focus-within {\n border-color: ", ";\n }\n "])), mixin.contents000), disabled && styled.css(_templateObject6 || (_templateObject6 = _taggedTemplateLiteral__default.default(["\n background-color: ", ";\n "])), mixin.bg200)];
22
+ return [$hasError ? styled.css(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral__default.default(["\n border-color: ", ";\n "])), mixin.roleRed) : styled.css(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral__default.default(["\n &:focus-within {\n border-color: ", ";\n }\n "])), mixin.contents000), disabled && styled.css(_templateObject6 || (_templateObject6 = _taggedTemplateLiteral__default.default(["\n background-color: ", ";\n "])), mixin.bg200)];
23
23
  });
24
24
  var InputDecorator = styled__default.default.div(_templateObject7 || (_templateObject7 = _taggedTemplateLiteral__default.default(["\n flex-shrink: 0;\n /* Inline\uC694\uC18C\uAC00 \uB4E4\uC5B4\uC624\uBA74 \uAC15\uC81C\uB85C block\uC73C\uB85C \uCC98\uB9AC (\uC911\uC559\uC815\uB82C\uC744 \uC704\uD574) */\n > * {\n display: block;\n }\n"])));
25
25
  var InputInner = styled__default.default.input(_templateObject8 || (_templateObject8 = _taggedTemplateLiteral__default.default(["\n ", "\n color: ", ";\n\n display: block;\n flex-grow: 1;\n width: 100%;\n padding: 10px 0;\n border: 0;\n background-color: transparent;\n\n &:placeholder-shown {\n ", "\n }\n\n &::placeholder {\n color: ", ";\n }\n\n &:focus {\n outline: none;\n }\n"])), mixin.getTypographyStyles('UIBody2'), mixin.contents000, mixin.ellipsis(), mixin.contents200);
@@ -1 +1 @@
1
- {"version":3,"file":"styles.cjs.js","sources":["../../../../src/Inputs/TextInput/styles.ts"],"sourcesContent":["'use client';\n\nimport type { ColorVariable } from '@remember-web/mixin';\nimport {\n bg200,\n contents000,\n contents200,\n contents300,\n ellipsis,\n getTypographyStyles,\n roleRed,\n} from '@remember-web/mixin';\nimport { formatUnit } from '@remember-web/shared';\nimport styled, { css } from 'styled-components';\n\nexport const InputWrapper = styled.div<{ $width?: string | number }>`\n ${({ $width }) =>\n $width &&\n css`\n width: ${formatUnit($width)};\n `};\n`;\n\nexport const InputContainer = styled.div<{\n disabled?: boolean;\n hasError?: boolean;\n}>`\n display: flex;\n align-items: center;\n border: 1px solid ${contents300};\n border-radius: 4px;\n padding: 0 12px;\n gap: 8px;\n\n transition:\n border-color 0.2s,\n background-color 0.2s;\n\n ${({ hasError, disabled }) => [\n hasError\n ? css`\n border-color: ${roleRed};\n `\n : css`\n &:focus-within {\n border-color: ${contents000};\n }\n `,\n disabled &&\n css`\n background-color: ${bg200};\n `,\n ]}\n`;\n\nexport const InputDecorator = styled.div`\n flex-shrink: 0;\n /* Inline요소가 들어오면 강제로 block으로 처리 (중앙정렬을 위해) */\n > * {\n display: block;\n }\n`;\n\nexport const InputInner = styled.input`\n ${getTypographyStyles('UIBody2')}\n color: ${contents000};\n\n display: block;\n flex-grow: 1;\n width: 100%;\n padding: 10px 0;\n border: 0;\n background-color: transparent;\n\n &:placeholder-shown {\n ${ellipsis()}\n }\n\n &::placeholder {\n color: ${contents200};\n }\n\n &:focus {\n outline: none;\n }\n`;\n\nexport const InputLabel = styled.label`\n ${getTypographyStyles('SubTitle1')}\n display: block;\n margin-bottom: 12px;\n display: flex;\n align-items: center;\n gap: 4px;\n\n & > mark {\n all: unset;\n color: ${roleRed};\n }\n`;\n\nexport const InputError = styled.div`\n ${getTypographyStyles('Caption1')}\n color: ${roleRed};\n\n margin-top: 8px;\n`;\n\nexport const InputHintText = styled.span<{ textColor?: ColorVariable }>`\n ${getTypographyStyles('UIBody2')}\n color: ${({ textColor }) => textColor};\n white-space: nowrap;\n`;\n\nexport const InputTogglePasswordVisibilityButton = styled.button`\n all: unset;\n appearance: none;\n cursor: pointer;\n flex-shrink: 0;\n\n & > svg {\n display: block;\n }\n`;\n"],"names":["InputWrapper","InputDecorator","InputTogglePasswordVisibilityButton"],"mappings":";;;;;;;;;;;;;AAAa;AAeAA;AACT;AAAS;AAIR;;AAkBD;;AAAqB;AActB;AAGUC;AAQN;;;;AA+CI;AAAY;AAAgB;AAI1BC;;;;;;;;;"}
1
+ {"version":3,"file":"styles.cjs.js","sources":["../../../../src/Inputs/TextInput/styles.ts"],"sourcesContent":["'use client';\n\nimport type { ColorVariable } from '@remember-web/mixin';\nimport {\n bg200,\n contents000,\n contents200,\n contents300,\n ellipsis,\n getTypographyStyles,\n roleRed,\n} from '@remember-web/mixin';\nimport { formatUnit } from '@remember-web/shared';\nimport styled, { css } from 'styled-components';\n\nexport const InputWrapper = styled.div<{ $width?: string | number }>`\n ${({ $width }) =>\n $width &&\n css`\n width: ${formatUnit($width)};\n `};\n`;\n\nexport const InputContainer = styled.div<{\n disabled?: boolean;\n $hasError?: boolean;\n}>`\n display: flex;\n align-items: center;\n border: 1px solid ${contents300};\n border-radius: 4px;\n padding: 0 12px;\n gap: 8px;\n\n transition:\n border-color 0.2s,\n background-color 0.2s;\n\n ${({ $hasError, disabled }) => [\n $hasError\n ? css`\n border-color: ${roleRed};\n `\n : css`\n &:focus-within {\n border-color: ${contents000};\n }\n `,\n disabled &&\n css`\n background-color: ${bg200};\n `,\n ]}\n`;\n\nexport const InputDecorator = styled.div`\n flex-shrink: 0;\n /* Inline요소가 들어오면 강제로 block으로 처리 (중앙정렬을 위해) */\n > * {\n display: block;\n }\n`;\n\nexport const InputInner = styled.input`\n ${getTypographyStyles('UIBody2')}\n color: ${contents000};\n\n display: block;\n flex-grow: 1;\n width: 100%;\n padding: 10px 0;\n border: 0;\n background-color: transparent;\n\n &:placeholder-shown {\n ${ellipsis()}\n }\n\n &::placeholder {\n color: ${contents200};\n }\n\n &:focus {\n outline: none;\n }\n`;\n\nexport const InputLabel = styled.label`\n ${getTypographyStyles('SubTitle1')}\n display: block;\n margin-bottom: 12px;\n display: flex;\n align-items: center;\n gap: 4px;\n\n & > mark {\n all: unset;\n color: ${roleRed};\n }\n`;\n\nexport const InputError = styled.div`\n ${getTypographyStyles('Caption1')}\n color: ${roleRed};\n\n margin-top: 8px;\n`;\n\nexport const InputHintText = styled.span<{ textColor?: ColorVariable }>`\n ${getTypographyStyles('UIBody2')}\n color: ${({ textColor }) => textColor};\n white-space: nowrap;\n`;\n\nexport const InputTogglePasswordVisibilityButton = styled.button`\n all: unset;\n appearance: none;\n cursor: pointer;\n flex-shrink: 0;\n\n & > svg {\n display: block;\n }\n`;\n"],"names":["InputWrapper","InputDecorator","InputTogglePasswordVisibilityButton"],"mappings":";;;;;;;;;;;;;AAAa;AAeAA;AACT;AAAS;AAIR;;AAkBD;;AAAsB;AAcvB;AAGUC;AAQN;;;;AA+CI;AAAY;AAAgB;AAI1BC;;;;;;;;;"}
@@ -4,7 +4,7 @@ export declare const InputWrapper: import("styled-components").IStyledComponent<
4
4
  }>>;
5
5
  export declare const InputContainer: import("styled-components").IStyledComponent<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
6
6
  disabled?: boolean | undefined;
7
- hasError?: boolean | undefined;
7
+ $hasError?: boolean | undefined;
8
8
  }>>;
9
9
  export declare const InputDecorator: import("styled-components").IStyledComponent<"web", import("styled-components/dist/types").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>>;
10
10
  export declare const InputInner: import("styled-components").IStyledComponent<"web", import("styled-components/dist/types").FastOmit<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, never>>;
@@ -10,9 +10,9 @@ var InputWrapper = styled.div(_templateObject || (_templateObject = _taggedTempl
10
10
  return $width && css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n width: ", ";\n "])), formatUnit($width));
11
11
  });
12
12
  var InputContainer = styled.div(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n display: flex;\n align-items: center;\n border: 1px solid ", ";\n border-radius: 4px;\n padding: 0 12px;\n gap: 8px;\n\n transition:\n border-color 0.2s,\n background-color 0.2s;\n\n ", "\n"])), contents300, function (_ref2) {
13
- var hasError = _ref2.hasError,
13
+ var $hasError = _ref2.$hasError,
14
14
  disabled = _ref2.disabled;
15
- return [hasError ? css(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["\n border-color: ", ";\n "])), roleRed) : css(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["\n &:focus-within {\n border-color: ", ";\n }\n "])), contents000), disabled && css(_templateObject6 || (_templateObject6 = _taggedTemplateLiteral(["\n background-color: ", ";\n "])), bg200)];
15
+ return [$hasError ? css(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["\n border-color: ", ";\n "])), roleRed) : css(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["\n &:focus-within {\n border-color: ", ";\n }\n "])), contents000), disabled && css(_templateObject6 || (_templateObject6 = _taggedTemplateLiteral(["\n background-color: ", ";\n "])), bg200)];
16
16
  });
17
17
  var InputDecorator = styled.div(_templateObject7 || (_templateObject7 = _taggedTemplateLiteral(["\n flex-shrink: 0;\n /* Inline\uC694\uC18C\uAC00 \uB4E4\uC5B4\uC624\uBA74 \uAC15\uC81C\uB85C block\uC73C\uB85C \uCC98\uB9AC (\uC911\uC559\uC815\uB82C\uC744 \uC704\uD574) */\n > * {\n display: block;\n }\n"])));
18
18
  var InputInner = styled.input(_templateObject8 || (_templateObject8 = _taggedTemplateLiteral(["\n ", "\n color: ", ";\n\n display: block;\n flex-grow: 1;\n width: 100%;\n padding: 10px 0;\n border: 0;\n background-color: transparent;\n\n &:placeholder-shown {\n ", "\n }\n\n &::placeholder {\n color: ", ";\n }\n\n &:focus {\n outline: none;\n }\n"])), getTypographyStyles('UIBody2'), contents000, ellipsis(), contents200);
@@ -1 +1 @@
1
- {"version":3,"file":"styles.esm.js","sources":["../../../../src/Inputs/TextInput/styles.ts"],"sourcesContent":["'use client';\n\nimport type { ColorVariable } from '@remember-web/mixin';\nimport {\n bg200,\n contents000,\n contents200,\n contents300,\n ellipsis,\n getTypographyStyles,\n roleRed,\n} from '@remember-web/mixin';\nimport { formatUnit } from '@remember-web/shared';\nimport styled, { css } from 'styled-components';\n\nexport const InputWrapper = styled.div<{ $width?: string | number }>`\n ${({ $width }) =>\n $width &&\n css`\n width: ${formatUnit($width)};\n `};\n`;\n\nexport const InputContainer = styled.div<{\n disabled?: boolean;\n hasError?: boolean;\n}>`\n display: flex;\n align-items: center;\n border: 1px solid ${contents300};\n border-radius: 4px;\n padding: 0 12px;\n gap: 8px;\n\n transition:\n border-color 0.2s,\n background-color 0.2s;\n\n ${({ hasError, disabled }) => [\n hasError\n ? css`\n border-color: ${roleRed};\n `\n : css`\n &:focus-within {\n border-color: ${contents000};\n }\n `,\n disabled &&\n css`\n background-color: ${bg200};\n `,\n ]}\n`;\n\nexport const InputDecorator = styled.div`\n flex-shrink: 0;\n /* Inline요소가 들어오면 강제로 block으로 처리 (중앙정렬을 위해) */\n > * {\n display: block;\n }\n`;\n\nexport const InputInner = styled.input`\n ${getTypographyStyles('UIBody2')}\n color: ${contents000};\n\n display: block;\n flex-grow: 1;\n width: 100%;\n padding: 10px 0;\n border: 0;\n background-color: transparent;\n\n &:placeholder-shown {\n ${ellipsis()}\n }\n\n &::placeholder {\n color: ${contents200};\n }\n\n &:focus {\n outline: none;\n }\n`;\n\nexport const InputLabel = styled.label`\n ${getTypographyStyles('SubTitle1')}\n display: block;\n margin-bottom: 12px;\n display: flex;\n align-items: center;\n gap: 4px;\n\n & > mark {\n all: unset;\n color: ${roleRed};\n }\n`;\n\nexport const InputError = styled.div`\n ${getTypographyStyles('Caption1')}\n color: ${roleRed};\n\n margin-top: 8px;\n`;\n\nexport const InputHintText = styled.span<{ textColor?: ColorVariable }>`\n ${getTypographyStyles('UIBody2')}\n color: ${({ textColor }) => textColor};\n white-space: nowrap;\n`;\n\nexport const InputTogglePasswordVisibilityButton = styled.button`\n all: unset;\n appearance: none;\n cursor: pointer;\n flex-shrink: 0;\n\n & > svg {\n display: block;\n }\n`;\n"],"names":["InputWrapper","InputDecorator","InputTogglePasswordVisibilityButton"],"mappings":";;;;;;AAAa;AAeAA;AACT;AAAS;AAIR;;AAkBD;;AAAqB;AActB;AAGUC;AAQN;;;;AA+CI;AAAY;AAAgB;AAI1BC;;"}
1
+ {"version":3,"file":"styles.esm.js","sources":["../../../../src/Inputs/TextInput/styles.ts"],"sourcesContent":["'use client';\n\nimport type { ColorVariable } from '@remember-web/mixin';\nimport {\n bg200,\n contents000,\n contents200,\n contents300,\n ellipsis,\n getTypographyStyles,\n roleRed,\n} from '@remember-web/mixin';\nimport { formatUnit } from '@remember-web/shared';\nimport styled, { css } from 'styled-components';\n\nexport const InputWrapper = styled.div<{ $width?: string | number }>`\n ${({ $width }) =>\n $width &&\n css`\n width: ${formatUnit($width)};\n `};\n`;\n\nexport const InputContainer = styled.div<{\n disabled?: boolean;\n $hasError?: boolean;\n}>`\n display: flex;\n align-items: center;\n border: 1px solid ${contents300};\n border-radius: 4px;\n padding: 0 12px;\n gap: 8px;\n\n transition:\n border-color 0.2s,\n background-color 0.2s;\n\n ${({ $hasError, disabled }) => [\n $hasError\n ? css`\n border-color: ${roleRed};\n `\n : css`\n &:focus-within {\n border-color: ${contents000};\n }\n `,\n disabled &&\n css`\n background-color: ${bg200};\n `,\n ]}\n`;\n\nexport const InputDecorator = styled.div`\n flex-shrink: 0;\n /* Inline요소가 들어오면 강제로 block으로 처리 (중앙정렬을 위해) */\n > * {\n display: block;\n }\n`;\n\nexport const InputInner = styled.input`\n ${getTypographyStyles('UIBody2')}\n color: ${contents000};\n\n display: block;\n flex-grow: 1;\n width: 100%;\n padding: 10px 0;\n border: 0;\n background-color: transparent;\n\n &:placeholder-shown {\n ${ellipsis()}\n }\n\n &::placeholder {\n color: ${contents200};\n }\n\n &:focus {\n outline: none;\n }\n`;\n\nexport const InputLabel = styled.label`\n ${getTypographyStyles('SubTitle1')}\n display: block;\n margin-bottom: 12px;\n display: flex;\n align-items: center;\n gap: 4px;\n\n & > mark {\n all: unset;\n color: ${roleRed};\n }\n`;\n\nexport const InputError = styled.div`\n ${getTypographyStyles('Caption1')}\n color: ${roleRed};\n\n margin-top: 8px;\n`;\n\nexport const InputHintText = styled.span<{ textColor?: ColorVariable }>`\n ${getTypographyStyles('UIBody2')}\n color: ${({ textColor }) => textColor};\n white-space: nowrap;\n`;\n\nexport const InputTogglePasswordVisibilityButton = styled.button`\n all: unset;\n appearance: none;\n cursor: pointer;\n flex-shrink: 0;\n\n & > svg {\n display: block;\n }\n`;\n"],"names":["InputWrapper","InputDecorator","InputTogglePasswordVisibilityButton"],"mappings":";;;;;;AAAa;AAeAA;AACT;AAAS;AAIR;;AAkBD;;AAAsB;AAcvB;AAGUC;AAQN;;;;AA+CI;AAAY;AAAgB;AAI1BC;;"}
@@ -31,6 +31,7 @@ var index$j = require('./Floating/Popover/index.cjs.js');
31
31
  var index$k = require('./Floating/Tooltip/index.cjs.js');
32
32
  var styles$2 = require('./Floating/DropdownMenu/styles.cjs.js');
33
33
  var styles$3 = require('./Floating/Popover/styles.cjs.js');
34
+ var index$l = require('./Chips/Chip/index.cjs.js');
34
35
 
35
36
 
36
37
 
@@ -80,4 +81,5 @@ exports.StyledPopoverContent = styles$3.StyledPopoverContent;
80
81
  exports.StyledPopoverContentWrapper = styles$3.StyledPopoverContentWrapper;
81
82
  exports.showFadeIn = styles$3.showFadeIn;
82
83
  exports.showFadeOut = styles$3.showFadeOut;
84
+ exports.Chip = index$l.Chip;
83
85
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -8,4 +8,5 @@ export * from './Modals';
8
8
  export * from './Paginations';
9
9
  export * from './Inputs';
10
10
  export * from './Floating';
11
+ export * from './Chips';
11
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC"}
@@ -29,4 +29,5 @@ export { default as Popover } from './Floating/Popover/index.esm.js';
29
29
  export { default as Tooltip } from './Floating/Tooltip/index.esm.js';
30
30
  export { DropdownMenuItemDisabledCSS, DropdownMenuItemHoverCSS, StyledDropdownMenuContent, StyledDropdownMenuContentWrapper, StyledDropdownMenuItem, StyledDropdownMenuSection, StyledDropdownMenuSectionTitle, dropdownMenuItemCSS, getDropdownMenuItemCss } from './Floating/DropdownMenu/styles.esm.js';
31
31
  export { StyledPopoverContent, StyledPopoverContentWrapper, showFadeIn, showFadeOut } from './Floating/Popover/styles.esm.js';
32
+ export { Chip } from './Chips/Chip/index.esm.js';
32
33
  //# sourceMappingURL=index.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -8,9 +8,10 @@ export declare const TitleContainer: import("styled-components").IStyledComponen
8
8
  export declare const Table: import("styled-components").IStyledComponent<"web", import("styled-components/dist/types").FastOmit<import("react").DetailedHTMLProps<import("react").TableHTMLAttributes<HTMLTableElement>, HTMLTableElement>, never>>;
9
9
  export declare const TableHeader: import("styled-components").IStyledComponent<"web", import("styled-components/dist/types").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLTableSectionElement>, HTMLTableSectionElement>, never>>;
10
10
  export declare const TableBody: import("styled-components").IStyledComponent<"web", import("styled-components/dist/types").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLTableSectionElement>, HTMLTableSectionElement>, never>>;
11
- export declare const TableColumn: ({ isHeader, align, children, }: {
11
+ export declare const TableColumn: ({ isHeader, align, rowSpan, children, }: {
12
12
  isHeader?: boolean;
13
13
  align?: TextAlign;
14
+ rowSpan?: number;
14
15
  children: ReactNode;
15
16
  }) => import("react/jsx-runtime").JSX.Element;
16
17
  export declare const TableRow: import("styled-components").IStyledComponent<"web", import("styled-components/dist/types").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLTableRowElement>, HTMLTableRowElement>, never>>;
@@ -1 +1 @@
1
- {"version":3,"file":"common.styles.d.ts","sourceRoot":"","sources":["../../../src/stories/common.styles.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,KAAK,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE7C,eAAO,MAAM,KAAK;;;GAmBjB,CAAC;AAEF,eAAO,MAAM,cAAc,gNAE1B,CAAC;AAEF,eAAO,MAAM,KAAK,yNAIjB,CAAC;AAEF,eAAO,MAAM,WAAW,kOAAiB,CAAC;AAE1C,eAAO,MAAM,SAAS,kOAAiB,CAAC;AAkBxC,eAAO,MAAM,WAAW,mCAIrB;IACD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,QAAQ,EAAE,SAAS,CAAC;CACrB,4CAKE,CAAC;AAEJ,eAAO,MAAM,QAAQ,0NAAc,CAAC"}
1
+ {"version":3,"file":"common.styles.d.ts","sourceRoot":"","sources":["../../../src/stories/common.styles.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,KAAK,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE7C,eAAO,MAAM,KAAK;;;GAmBjB,CAAC;AAEF,eAAO,MAAM,cAAc,gNAE1B,CAAC;AAEF,eAAO,MAAM,KAAK,yNAIjB,CAAC;AAEF,eAAO,MAAM,WAAW,kOAAiB,CAAC;AAE1C,eAAO,MAAM,SAAS,kOAAiB,CAAC;AAkBxC,eAAO,MAAM,WAAW,4CAKrB;IACD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;CACrB,4CASE,CAAC;AAEJ,eAAO,MAAM,QAAQ,0NAAc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remember-web/primitive",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "description": "Remember Web Primitive Components",
5
5
  "homepage": "https://dramancompany.github.io/remember-web-packages/",
6
6
  "author": "Remember",
@@ -42,7 +42,7 @@
42
42
  "@radix-ui/react-switch": "^1.0.3",
43
43
  "@radix-ui/react-tooltip": "^1.0.7",
44
44
  "@remember-web/icon": "^0.1.12",
45
- "@remember-web/mixin": "^0.2.5",
45
+ "@remember-web/mixin": "^0.2.6",
46
46
  "@remember-web/shared": "^0.1.1"
47
47
  },
48
48
  "devDependencies": {
@@ -0,0 +1,138 @@
1
+ import {
2
+ getIconComponentFromName,
3
+ iconNames,
4
+ isIconName,
5
+ } from '@/stories/util';
6
+ import type { Meta, StoryObj } from '@storybook/react';
7
+ import { Fragment, createElement } from 'react';
8
+
9
+ import { Typography } from '@/Common';
10
+ import {
11
+ Paper,
12
+ Table,
13
+ TableBody,
14
+ TableColumn,
15
+ TableHeader,
16
+ TableRow,
17
+ } from '@/stories/common.styles';
18
+ import { IconArrow2LeftS } from '@remember-web/icon';
19
+ import { Chip } from './';
20
+ import type { ChipSize } from './types';
21
+
22
+ type Story = StoryObj<typeof Chip>;
23
+
24
+ const meta = {
25
+ title: 'Primitive/Chips/Chip',
26
+ component: Chip,
27
+ argTypes: {
28
+ variant: {
29
+ control: 'select',
30
+ options: ['filled', 'outline', 'dashedLine'],
31
+ },
32
+ size: { control: 'select', options: ['small', 'medium'] },
33
+ children: { control: 'text' },
34
+ disabled: { control: 'boolean' },
35
+ selected: { control: 'boolean' },
36
+ clickable: { control: 'boolean' },
37
+ onDelete: { action: 'deleted' },
38
+ leftIcon: { control: 'select', options: ['none', ...iconNames] },
39
+ deleteIcon: { control: 'select', options: ['none', ...iconNames] },
40
+ },
41
+ args: {
42
+ children: 'Test Chip',
43
+ onDelete: () => console.log('Delete'),
44
+ size: 'medium',
45
+ variant: 'filled',
46
+ clickable: true,
47
+ selected: false,
48
+ disabled: false,
49
+ },
50
+ } satisfies Meta<typeof Chip>;
51
+
52
+ export const Default: Story = {
53
+ render: ({ leftIcon, deleteIcon, selected, clickable, ...args }) => {
54
+ const leftIconString = String(leftIcon);
55
+ const leftIconElement =
56
+ leftIcon && isIconName(leftIconString)
57
+ ? createElement(getIconComponentFromName(leftIconString))
58
+ : undefined;
59
+
60
+ const rightIconString = String(deleteIcon);
61
+ const deleteIconElement =
62
+ rightIconString && isIconName(rightIconString)
63
+ ? createElement(getIconComponentFromName(rightIconString))
64
+ : undefined;
65
+
66
+ return (
67
+ <Chip
68
+ {...args}
69
+ key={JSON.stringify(args)}
70
+ leftIcon={leftIconElement}
71
+ deleteIcon={deleteIconElement}
72
+ onDelete={args.onDelete || (() => {})}
73
+ />
74
+ );
75
+ },
76
+ };
77
+
78
+ const variants = ['filled', 'outline', 'dashedLine'] as const;
79
+ const sizes = ['medium', 'small'] as const;
80
+ const states = ['default', 'hover', 'disabled', 'selected'] as const;
81
+
82
+ export const Overview: Story = {
83
+ render: () => (
84
+ <Paper $minWidth={800} $maxWidth={1200}>
85
+ <Typography variant="Headline">Chip Overview</Typography>
86
+ <br />
87
+ <Table>
88
+ <TableHeader>
89
+ <TableRow>
90
+ <TableColumn isHeader>State</TableColumn>
91
+ <TableColumn isHeader>Size</TableColumn>
92
+ {variants.map((variant) => (
93
+ <TableColumn key={variant} isHeader align="center">
94
+ {variant.charAt(0).toUpperCase() + variant.slice(1)}
95
+ </TableColumn>
96
+ ))}
97
+ </TableRow>
98
+ </TableHeader>
99
+ <TableBody>
100
+ {states.map((state) => (
101
+ <Fragment key={state}>
102
+ {sizes.map((size: ChipSize, index: number) => (
103
+ <TableRow key={`${state}-${size}`}>
104
+ {index === 0 && (
105
+ <TableColumn rowSpan={2}>
106
+ {state.charAt(0).toUpperCase() + state.slice(1)}
107
+ </TableColumn>
108
+ )}
109
+ <TableColumn>
110
+ {size.charAt(0).toUpperCase() + size.slice(1)}
111
+ </TableColumn>
112
+ {variants.map((variant) => (
113
+ <TableColumn key={variant} align="center">
114
+ <Chip
115
+ size={size}
116
+ variant={variant}
117
+ clickable={state !== 'disabled' || true}
118
+ disabled={state === 'disabled'}
119
+ selected={state === 'selected'}
120
+ className={state === 'hover' ? 'hover-state' : ''}
121
+ onDelete={() => console.log('Delete')}
122
+ leftIcon={<IconArrow2LeftS />}
123
+ >
124
+ 칩이름
125
+ </Chip>
126
+ </TableColumn>
127
+ ))}
128
+ </TableRow>
129
+ ))}
130
+ </Fragment>
131
+ ))}
132
+ </TableBody>
133
+ </Table>
134
+ </Paper>
135
+ ),
136
+ };
137
+
138
+ export default meta;
@@ -0,0 +1,115 @@
1
+ import {
2
+ bg100,
3
+ bg200,
4
+ bg300,
5
+ contents100,
6
+ contents150,
7
+ contents200,
8
+ contents300,
9
+ contents999,
10
+ primary100,
11
+ } from '@remember-web/mixin';
12
+ import type { ChipSize, ChipVariant, ChipVariantStyleMap } from './types';
13
+
14
+ export const CHIP_SIZE_STYLE = {
15
+ small: {
16
+ typography: 'Caption1',
17
+ padding: '8px 10px',
18
+ height: '28px',
19
+ },
20
+ medium: {
21
+ typography: 'UIBody3',
22
+ padding: '8px 12px',
23
+ height: '30px',
24
+ },
25
+ } as const satisfies Record<ChipSize, unknown>;
26
+
27
+ export const CHIP_VARIANT_STYLE: ChipVariantStyleMap = {
28
+ filled: {
29
+ default: {
30
+ backgroundColor: bg200,
31
+ color: contents150,
32
+ leftIconColor: contents150,
33
+ deleteButtonColor: contents200,
34
+ },
35
+ hover: {
36
+ backgroundColor: bg200,
37
+ color: contents100,
38
+ leftIconColor: contents100,
39
+ deleteButtonColor: contents150,
40
+ },
41
+ disabled: {
42
+ backgroundColor: bg300,
43
+ color: contents300,
44
+ leftIconColor: contents300,
45
+ deleteButtonColor: contents300,
46
+ },
47
+ selected: {
48
+ backgroundColor: primary100,
49
+ color: contents999,
50
+ leftIconColor: contents999,
51
+ deleteButtonColor: contents999,
52
+ },
53
+ },
54
+
55
+ outline: {
56
+ default: {
57
+ backgroundColor: bg100,
58
+ color: contents150,
59
+ leftIconColor: contents150,
60
+ deleteButtonColor: contents200,
61
+ border: `1px solid ${contents150}`,
62
+ },
63
+ hover: {
64
+ backgroundColor: bg100,
65
+ color: contents100,
66
+ leftIconColor: contents100,
67
+ deleteButtonColor: contents150,
68
+ border: `1px solid ${contents100}`,
69
+ },
70
+ disabled: {
71
+ backgroundColor: bg100,
72
+ color: contents200,
73
+ leftIconColor: contents200,
74
+ deleteButtonColor: contents200,
75
+ border: `1px solid ${contents200}`,
76
+ },
77
+ selected: {
78
+ backgroundColor: primary100,
79
+ color: contents999,
80
+ leftIconColor: contents999,
81
+ deleteButtonColor: contents999,
82
+ },
83
+ },
84
+
85
+ dashedLine: {
86
+ default: {
87
+ backgroundColor: bg100,
88
+ color: contents150,
89
+ leftIconColor: contents150,
90
+ deleteButtonColor: contents200,
91
+ border: `1px dashed ${contents150}`,
92
+ },
93
+ hover: {
94
+ backgroundColor: bg100,
95
+ color: contents100,
96
+ leftIconColor: contents100,
97
+ deleteButtonColor: contents150,
98
+ border: `1px dashed ${contents100}`,
99
+ },
100
+ disabled: {
101
+ backgroundColor: bg100,
102
+ color: contents200,
103
+ leftIconColor: contents200,
104
+ deleteButtonColor: contents200,
105
+ border: `1px dashed ${contents200}`,
106
+ },
107
+ selected: {
108
+ backgroundColor: primary100,
109
+ color: contents999,
110
+ leftIconColor: contents999,
111
+ deleteButtonColor: contents999,
112
+ border: `1px solid ${primary100}`,
113
+ },
114
+ },
115
+ } as const satisfies Record<ChipVariant, unknown>;