myoperator-ui 0.0.138 → 0.0.139

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 (2) hide show
  1. package/dist/index.js +186 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1686,6 +1686,192 @@ const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(
1686
1686
  TextField.displayName = "TextField";
1687
1687
 
1688
1688
  export { TextField, textFieldContainerVariants, textFieldInputVariants };
1689
+ `, prefix)
1690
+ }
1691
+ ]
1692
+ },
1693
+ "copyable-field": {
1694
+ name: "copyable-field",
1695
+ description: "A read-only field with copy-to-clipboard functionality. Supports secret mode for sensitive data like API keys.",
1696
+ dependencies: [
1697
+ "clsx",
1698
+ "tailwind-merge",
1699
+ "lucide-react"
1700
+ ],
1701
+ files: [
1702
+ {
1703
+ name: "copyable-field.tsx",
1704
+ content: prefixTailwindClasses(`import * as React from "react";
1705
+ import { Copy, Check, Eye, EyeOff } from "lucide-react";
1706
+ import { cn } from "../../lib/utils";
1707
+
1708
+ export interface CopyableFieldProps
1709
+ extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
1710
+ /** Label text displayed above the field */
1711
+ label: string;
1712
+ /** Value to display and copy */
1713
+ value: string;
1714
+ /** Helper text displayed below the field */
1715
+ helperText?: string;
1716
+ /** When true, masks the value with dots and shows eye toggle */
1717
+ secret?: boolean;
1718
+ /** Header action (e.g., "Regenerate" link) */
1719
+ headerAction?: {
1720
+ label: string;
1721
+ onClick: () => void;
1722
+ };
1723
+ /** Callback when value is copied */
1724
+ onValueCopy?: (value: string) => void;
1725
+ /** Additional class for the input container */
1726
+ inputClassName?: string;
1727
+ }
1728
+
1729
+ /**
1730
+ * CopyableField displays a read-only value with copy-to-clipboard functionality.
1731
+ * Supports secret mode for sensitive data like API keys and passwords.
1732
+ *
1733
+ * @example
1734
+ * \`\`\`tsx
1735
+ * // Simple copyable field
1736
+ * <CopyableField
1737
+ * label="Base URL"
1738
+ * value="https://api.myoperator.co/v3/voice/gateway"
1739
+ * />
1740
+ *
1741
+ * // Secret field with regenerate action
1742
+ * <CopyableField
1743
+ * label="Authentication"
1744
+ * value="sk_live_abc123xyz"
1745
+ * secret
1746
+ * helperText="Used for client-side integrations."
1747
+ * headerAction={{
1748
+ * label: "Regenerate",
1749
+ * onClick: () => console.log("Regenerate clicked"),
1750
+ * }}
1751
+ * />
1752
+ * \`\`\`
1753
+ */
1754
+ export const CopyableField = React.forwardRef<HTMLDivElement, CopyableFieldProps>(
1755
+ (
1756
+ {
1757
+ label,
1758
+ value,
1759
+ helperText,
1760
+ secret = false,
1761
+ headerAction,
1762
+ onValueCopy,
1763
+ className,
1764
+ inputClassName,
1765
+ ...props
1766
+ },
1767
+ ref
1768
+ ) => {
1769
+ const [copied, setCopied] = React.useState(false);
1770
+ const [isVisible, setIsVisible] = React.useState(!secret);
1771
+
1772
+ const handleCopy = async () => {
1773
+ try {
1774
+ await navigator.clipboard.writeText(value);
1775
+ setCopied(true);
1776
+ onValueCopy?.(value);
1777
+ setTimeout(() => setCopied(false), 2000);
1778
+ } catch {
1779
+ // Clipboard API may fail in insecure contexts
1780
+ }
1781
+ };
1782
+
1783
+ const toggleVisibility = () => {
1784
+ setIsVisible((prev) => !prev);
1785
+ };
1786
+
1787
+ // Display masked or actual value
1788
+ const displayValue = secret && !isVisible ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" : value;
1789
+
1790
+ return (
1791
+ <div
1792
+ ref={ref}
1793
+ className={cn("flex flex-col gap-1", className)}
1794
+ {...props}
1795
+ >
1796
+ {/* Header Row: Label + Optional Action */}
1797
+ <div className="flex items-start justify-between">
1798
+ <label className="text-sm text-semantic-text-muted tracking-[0.035px]">
1799
+ {label}
1800
+ </label>
1801
+ {headerAction && (
1802
+ <button
1803
+ type="button"
1804
+ onClick={headerAction.onClick}
1805
+ className="text-sm font-semibold text-semantic-text-muted tracking-[0.014px] hover:text-semantic-text-primary transition-colors"
1806
+ >
1807
+ {headerAction.label}
1808
+ </button>
1809
+ )}
1810
+ </div>
1811
+
1812
+ {/* Input Container */}
1813
+ <div
1814
+ className={cn(
1815
+ "flex h-11 items-center justify-between rounded border border-semantic-border-layout bg-semantic-bg-ui pl-4 pr-2.5 py-2.5",
1816
+ inputClassName
1817
+ )}
1818
+ >
1819
+ {/* Value Display */}
1820
+ <span className="text-base text-[var(--color-primary-950)] tracking-[0.08px] truncate">
1821
+ {displayValue}
1822
+ </span>
1823
+
1824
+ {/* Action Icons */}
1825
+ <div className="flex items-center gap-4 shrink-0">
1826
+ {/* Eye Toggle (only for secret mode) */}
1827
+ {secret && (
1828
+ <button
1829
+ type="button"
1830
+ onClick={toggleVisibility}
1831
+ className="text-semantic-text-muted hover:text-semantic-text-primary transition-colors"
1832
+ aria-label={isVisible ? "Hide value" : "Show value"}
1833
+ >
1834
+ {isVisible ? (
1835
+ <EyeOff className="size-[18px]" />
1836
+ ) : (
1837
+ <Eye className="size-[18px]" />
1838
+ )}
1839
+ </button>
1840
+ )}
1841
+
1842
+ {/* Copy Button */}
1843
+ <button
1844
+ type="button"
1845
+ onClick={handleCopy}
1846
+ className={cn(
1847
+ "transition-colors",
1848
+ copied
1849
+ ? "text-semantic-success-primary"
1850
+ : "text-semantic-text-muted hover:text-semantic-text-primary"
1851
+ )}
1852
+ aria-label={copied ? "Copied" : "Copy to clipboard"}
1853
+ >
1854
+ {copied ? (
1855
+ <Check className="size-[18px]" />
1856
+ ) : (
1857
+ <Copy className="size-[18px]" />
1858
+ )}
1859
+ </button>
1860
+ </div>
1861
+ </div>
1862
+
1863
+ {/* Helper Text */}
1864
+ {helperText && (
1865
+ <p className="m-0 text-sm text-semantic-text-muted tracking-[0.035px]">
1866
+ {helperText}
1867
+ </p>
1868
+ )}
1869
+ </div>
1870
+ );
1871
+ }
1872
+ );
1873
+
1874
+ CopyableField.displayName = "CopyableField";
1689
1875
  `, prefix)
1690
1876
  }
1691
1877
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myoperator-ui",
3
- "version": "0.0.138",
3
+ "version": "0.0.139",
4
4
  "description": "CLI for adding myOperator UI components to your project",
5
5
  "type": "module",
6
6
  "exports": "./dist/index.js",