@dile/ui 2.18.3 → 2.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,87 @@
1
+ # dile-copy-markdown-url
2
+
3
+ Un componente Web que permite copiar el contenido de una URL al portapapeles. Reutiliza el componente `dile-copy-text` y usa fetch para obtener el contenido de la URL de forma simple y eficiente.
4
+
5
+ ## Instalación
6
+
7
+ ```bash
8
+ npm install @dile/ui
9
+ ```
10
+
11
+ ## Importación
12
+
13
+ ```javascript
14
+ import '@dile/ui/components/copy-markdown-url/copy-markdown-url.js';
15
+ ```
16
+
17
+ ## Uso
18
+
19
+ ```html
20
+ <dile-copy-markdown-url
21
+ url="https://ejemplo.com/archivo.md"
22
+ >
23
+ Copiar markdown
24
+ </dile-copy-markdown-url>
25
+ ```
26
+
27
+ ## Propiedades
28
+
29
+ - **url** (String): La URL del contenido a copiar
30
+ - **copiedDuration** (Number): Duración en milisegundos del feedback de copia (por defecto: 1000)
31
+ - **feedbackText** (String): Texto del feedback visual (por defecto: 'Copied!')
32
+ - **hideIcon** (Boolean): Ocultar el icono en el feedback (por defecto: false)
33
+
34
+ ## Eventos
35
+
36
+ Hereda todos los eventos de `dile-copy-text`:
37
+
38
+ - **dile-text-copied**: Se dispara cuando el contenido se ha copiado correctamente
39
+ - `detail.text`: El contenido que se copió
40
+
41
+ Además, dispara:
42
+
43
+ - **dile-copy-markdown-url-error**: Se dispara cuando hay un error al obtener el contenido de la URL
44
+ - `detail.message`: Descripción del error
45
+
46
+ ## Estilos CSS personalizables
47
+
48
+ El componente hereda los estilos de `dile-copy-text`, así que puedes usar las mismas variables CSS:
49
+
50
+ - `--dile-copy-text-text-decoration`: Decoración del texto del enlace (por defecto: none)
51
+ - `--dile-copy-text-color`: Color del texto del enlace (por defecto: inherit)
52
+ - `--dile-copy-text-transition-duration`: Duración de la transición (por defecto: 0.3s)
53
+ - `--dile-copy-text-hover-color`: Color del texto al hacer hover (por defecto: #0066cc)
54
+ - `--dile-copy-text-hover-text-decoration`: Decoración al hacer hover (por defecto: underline)
55
+ - `--dile-copy-text-focus-outline`: Contorno al tener enfoque (por defecto: 2px solid #0066cc)
56
+
57
+ ## Ejemplo completo
58
+
59
+ ```html
60
+ <dile-copy-markdown-url
61
+ url="https://raw.githubusercontent.com/user/repo/main/README.md"
62
+ feedbackText="¡Markdown copiado!"
63
+ copiedDuration="2000"
64
+ >
65
+ 📋 Copiar README
66
+ </dile-copy-markdown-url>
67
+
68
+ <script type="module">
69
+ const copyBtn = document.querySelector('dile-copy-markdown-url');
70
+
71
+ copyBtn.addEventListener('dile-text-copied', (e) => {
72
+ console.log('Contenido copiado:', e.detail.text);
73
+ });
74
+
75
+ copyBtn.addEventListener('dile-copy-markdown-url-error', (e) => {
76
+ console.error('Error:', e.detail.message);
77
+ });
78
+ </script>
79
+ ```
80
+
81
+ ## Comportamiento
82
+
83
+ 1. El usuario hace click en el componente
84
+ 2. Si es la primera vez, el componente hace un fetch a la URL especificada
85
+ 3. Una vez obtiene el contenido, automáticamente lo copia al portapapeles
86
+ 4. Se muestra un feedback visual indicando que el contenido se copió
87
+ 5. En los siguientes clicks, el contenido ya está cacheado y se copia directamente
@@ -0,0 +1,3 @@
1
+ import { DileCopyMarkdownUrl } from "./index.js";
2
+
3
+ export { DileCopyMarkdownUrl };
@@ -0,0 +1,5 @@
1
+ import { DileCopyMarkdownUrl } from './src/DileCopyMarkdownUrl.js';
2
+
3
+ window.customElements.define('dile-copy-markdown-url', DileCopyMarkdownUrl);
4
+
5
+ export { DileCopyMarkdownUrl };
@@ -0,0 +1,99 @@
1
+ import { LitElement, html } from 'lit';
2
+ import '../../copy-text/copy-text.js';
3
+
4
+ export class DileCopyMarkdownUrl extends LitElement {
5
+ static get properties() {
6
+ return {
7
+ url: { type: String },
8
+ copiedDuration: { type: Number },
9
+ feedbackText: { type: String },
10
+ hideIcon: { type: Boolean },
11
+ loading: { type: Boolean, state: true },
12
+ error: { type: String, state: true },
13
+ content: { type: String, state: true }
14
+ };
15
+ }
16
+
17
+ constructor() {
18
+ super();
19
+ this.url = '';
20
+ this.copiedDuration = 1000;
21
+ this.feedbackText = 'Copied!';
22
+ this.hideIcon = false;
23
+ this.loading = false;
24
+ this.error = null;
25
+ this.content = '';
26
+ }
27
+
28
+ render() {
29
+ return html`
30
+ <dile-copy-text
31
+ id="copy-component"
32
+ .content="${this.content}"
33
+ .feedbackText="${this.feedbackText}"
34
+ .copiedDuration="${this.copiedDuration}"
35
+ ?hideIcon="${this.hideIcon}"
36
+ @click="${this.handleClick}"
37
+ >
38
+ <slot></slot>
39
+ </dile-copy-text>
40
+ `;
41
+ }
42
+
43
+ async handleClick(e) {
44
+ if (this.loading) {
45
+ e.preventDefault();
46
+ return;
47
+ }
48
+
49
+ if (!this.content && this.url) {
50
+ e.preventDefault();
51
+ await this.fetchContent();
52
+
53
+ // After fetching, trigger copy on the component using its public API
54
+ const copyComponent = this.shadowRoot.querySelector('#copy-component');
55
+ if (copyComponent && this.content) {
56
+ await copyComponent.copy();
57
+ }
58
+ }
59
+ }
60
+
61
+ async fetchContent() {
62
+ if (!this.url) {
63
+ this.error = 'URL is not set';
64
+ this.dispatchEvent(
65
+ new CustomEvent('dile-copy-markdown-url-error', {
66
+ detail: { message: this.error },
67
+ bubbles: true,
68
+ composed: true
69
+ })
70
+ );
71
+ return;
72
+ }
73
+
74
+ this.loading = true;
75
+ this.error = null;
76
+
77
+ try {
78
+ const response = await fetch(this.url);
79
+
80
+ if (!response.ok) {
81
+ throw new Error(`HTTP error! status: ${response.status}`);
82
+ }
83
+
84
+ this.content = await response.text();
85
+ } catch (err) {
86
+ this.error = err.message || 'Error fetching content';
87
+
88
+ this.dispatchEvent(
89
+ new CustomEvent('dile-copy-markdown-url-error', {
90
+ detail: { message: this.error },
91
+ bubbles: true,
92
+ composed: true
93
+ })
94
+ );
95
+ } finally {
96
+ this.loading = false;
97
+ }
98
+ }
99
+ }
@@ -30,7 +30,7 @@ export class DileCopyText extends LitElement {
30
30
 
31
31
  static get properties() {
32
32
  return {
33
- copy: { type: String },
33
+ content: { type: String },
34
34
  copiedDuration: { type: Number },
35
35
  feedbackText: { type: String },
36
36
  hideIcon: { type: Boolean }
@@ -39,7 +39,7 @@ export class DileCopyText extends LitElement {
39
39
 
40
40
  constructor() {
41
41
  super();
42
- this.copy = '';
42
+ this.content = '';
43
43
  this.copiedDuration = 1000; // 2 seconds by default
44
44
  this.feedbackText = 'Copied!';
45
45
  this.hideIcon = false;
@@ -47,22 +47,23 @@ export class DileCopyText extends LitElement {
47
47
 
48
48
  render() {
49
49
  return html`
50
- <a
51
- href="#"
52
- role="button"
53
- tabindex="0"
54
- @click="${this.handleCopy}"
55
- @keydown="${this.handleKeydown}"
56
- >
57
- <slot></slot>
58
- </a>
59
50
  <dile-floating-feedback
60
51
  id="copy-feedback"
61
52
  feedback="${this.feedbackText}"
62
53
  duration="${this.copiedDuration}"
63
54
  ?hideIcon=${this.hideIcon}
64
55
  .icon=${contentCopyIcon}
65
- ></dile-floating-feedback>
56
+ >
57
+ <a
58
+ href="#"
59
+ role="button"
60
+ tabindex="0"
61
+ @click="${this.handleCopy}"
62
+ @keydown="${this.handleKeydown}"
63
+ >
64
+ <slot></slot>
65
+ </a>
66
+ </dile-floating-feedback>
66
67
  `;
67
68
  }
68
69
 
@@ -82,7 +83,7 @@ export class DileCopyText extends LitElement {
82
83
  try {
83
84
  // Try to use Clipboard API first (modern browsers)
84
85
  if (navigator.clipboard && navigator.clipboard.writeText) {
85
- await navigator.clipboard.writeText(this.copy);
86
+ await navigator.clipboard.writeText(this.content);
86
87
  } else {
87
88
  // Fallback for older browsers
88
89
  this.copyWithExecCommand();
@@ -91,7 +92,7 @@ export class DileCopyText extends LitElement {
91
92
  // Dispatch custom event
92
93
  this.dispatchEvent(
93
94
  new CustomEvent('dile-text-copied', {
94
- detail: { text: this.copy },
95
+ detail: { text: this.content },
95
96
  bubbles: true,
96
97
  composed: true
97
98
  })
@@ -106,7 +107,7 @@ export class DileCopyText extends LitElement {
106
107
  this.copyWithExecCommand();
107
108
  this.dispatchEvent(
108
109
  new CustomEvent('dile-text-copied', {
109
- detail: { text: this.copy },
110
+ detail: { text: this.content },
110
111
  bubbles: true,
111
112
  composed: true
112
113
  })
@@ -120,7 +121,7 @@ export class DileCopyText extends LitElement {
120
121
 
121
122
  copyWithExecCommand() {
122
123
  const textArea = document.createElement('textarea');
123
- textArea.value = this.copy;
124
+ textArea.value = this.content;
124
125
  textArea.style.position = 'fixed';
125
126
  textArea.style.left = '-999999px';
126
127
  textArea.style.top = '-999999px';
@@ -140,4 +141,8 @@ export class DileCopyText extends LitElement {
140
141
  feedback.show();
141
142
  }
142
143
  }
144
+
145
+ async copy() {
146
+ await this.copyToClipboard();
147
+ }
143
148
  }
@@ -35,7 +35,7 @@ export class DileFloatingFeedback extends LitElement {
35
35
 
36
36
  render() {
37
37
  return html`
38
- <div class="feedback-anchor"></div>
38
+ <slot class="feedback-anchor"></slot>
39
39
  `;
40
40
  }
41
41
 
@@ -116,8 +116,15 @@ export class DileFloatingFeedback extends LitElement {
116
116
  // Add content container to floating element
117
117
  floatingElement.appendChild(contentContainer);
118
118
 
119
- // Calculate position relative to this component
120
- const rect = this.getBoundingClientRect();
119
+ // Calculate position relative to the slot's content
120
+ const anchorElement = this.children[0];
121
+ if (!anchorElement) {
122
+ console.warn('dile-floating-feedback: No element in slot to anchor to');
123
+ floatingElement.remove();
124
+ return;
125
+ }
126
+
127
+ const rect = anchorElement.getBoundingClientRect();
121
128
  const x = rect.left + rect.width / 2;
122
129
  const y = rect.top;
123
130
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dile/ui",
3
- "version": "2.18.3",
3
+ "version": "2.20.0",
4
4
  "description": "UI Core components from dile-components.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -26,5 +26,5 @@
26
26
  "publishConfig": {
27
27
  "access": "public"
28
28
  },
29
- "gitHead": "5a5d851418d9a02f6cf24e937005ee9361085678"
29
+ "gitHead": "cd0b6acfaed41004ccd714f0ad586bc66b303479"
30
30
  }