delon-util

@delon/util skill - Utility functions library for array, string, date, number manipulation. For ng-events construction site progress tracking system.

242 stars

Best use case

delon-util is best used when you need a repeatable AI agent workflow instead of a one-off prompt. It is especially useful for teams working in multi. @delon/util skill - Utility functions library for array, string, date, number manipulation. For ng-events construction site progress tracking system.

@delon/util skill - Utility functions library for array, string, date, number manipulation. For ng-events construction site progress tracking system.

Users should expect a more consistent workflow output, faster repeated execution, and less time spent rewriting prompts from scratch.

Practical example

Example input

Use the "delon-util" skill to help with this workflow task. Context: @delon/util skill - Utility functions library for array, string, date, number manipulation. For ng-events construction site progress tracking system.

Example output

A structured workflow result with clearer steps, more consistent formatting, and an output that is easier to reuse in the next run.

When to use this skill

  • Use this skill when you want a reusable workflow rather than writing the same prompt again and again.

When not to use this skill

  • Do not use this when you only need a one-off answer and do not need a reusable workflow.
  • Do not use it if you cannot install or maintain the related files, repository context, or supporting tools.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/delon-util/SKILL.md --create-dirs "https://raw.githubusercontent.com/aiskillstore/marketplace/main/skills/7spade/delon-util/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/delon-util/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How delon-util Compares

Feature / Agentdelon-utilStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

@delon/util skill - Utility functions library for array, string, date, number manipulation. For ng-events construction site progress tracking system.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# @delon/util - Utility Functions Library

Trigger patterns: "utility", "helper", "@delon/util", "format", "deepCopy", "deepMerge"

## Overview

@delon/util provides a comprehensive collection of utility functions for common data manipulation tasks in ng-alain applications.

**Package**: @delon/util@20.1.0

## Categories

### 1. Array Utilities (`array/`)

#### deepCopy - Deep Copy Arrays/Objects

```typescript
import { deepCopy } from '@delon/util/array';

const original = { name: '任務', items: [1, 2, 3], meta: { id: 1 } };
const copy = deepCopy(original);

// Changes to copy won't affect original
copy.items.push(4);
console.log(original.items); // [1, 2, 3]
console.log(copy.items);     // [1, 2, 3, 4]
```

**Use Cases**:
- Clone state objects for immutability
- Create independent copies before mutations
- Deep cloning form data

#### deepMerge - Deep Merge Objects

```typescript
import { deepMerge } from '@delon/util/array';

const defaults = {
  config: { theme: 'light', size: 'default' },
  features: ['dashboard']
};

const custom = {
  config: { theme: 'dark' },
  features: ['reports']
};

const merged = deepMerge(defaults, custom);
// Result: {
//   config: { theme: 'dark', size: 'default' },
//   features: ['dashboard', 'reports']
// }
```

#### Other Array Functions

```typescript
import { 
  groupBy,     // Group array by property
  uniq,        // Remove duplicates
  uniqBy,      // Remove duplicates by property
  orderBy      // Sort array by properties
} from '@delon/util/array';

// Group tasks by status
const grouped = groupBy(tasks, 'status');
// { pending: [...], completed: [...] }

// Remove duplicate IDs
const uniqueIds = uniq([1, 2, 2, 3]); // [1, 2, 3]

// Remove duplicate tasks by ID
const uniqueTasks = uniqBy(tasks, 'id');

// Sort tasks
const sorted = orderBy(tasks, ['priority', 'createdAt'], ['asc', 'desc']);
```

### 2. String Utilities (`string/`)

#### format - String Formatting

```typescript
import { format } from '@delon/util/string';

// Template interpolation
const message = format('任務 {0} 已指派給 {1}', taskName, userName);

// Named parameters
const message2 = format('任務 {name} 的狀態為 {status}', { 
  name: '地基施工', 
  status: '進行中' 
});
```

#### Other String Functions

```typescript
import { 
  toCamelCase,    // Convert to camelCase
  toPascalCase,   // Convert to PascalCase
  toKebabCase,    // Convert to kebab-case
  toSnakeCase,    // Convert to snake_case
  truncate        // Truncate with ellipsis
} from '@delon/util/string';

toCamelCase('task-name');     // 'taskName'
toPascalCase('task-name');    // 'TaskName'
toKebabCase('TaskName');      // 'task-name'
toSnakeCase('TaskName');      // 'task_name'
truncate('Long text...', 10); // 'Long te...'
```

### 3. Date Utilities (`date/`)

#### getTimeDistance - Get Time Ranges

```typescript
import { getTimeDistance } from '@delon/util/date';

// Get today's date range
const today = getTimeDistance('today');
// [Date(2024-12-25 00:00:00), Date(2024-12-25 23:59:59)]

// Get this week's date range
const week = getTimeDistance('week');

// Get this month's date range
const month = getTimeDistance('month');

// Get this year's date range
const year = getTimeDistance('year');

// Custom range with offset
const lastWeek = getTimeDistance('week', -1);
```

**Supported Types**:
- `'today'` - Current day
- `'week'` - Current week (Sunday to Saturday)
- `'month'` - Current month
- `'year'` - Current year
- Custom offset (negative for past, positive for future)

#### formatDistanceToNow - Relative Time

```typescript
import { formatDistanceToNow } from '@delon/util/date';

const createdAt = new Date('2024-12-20');
const relative = formatDistanceToNow(createdAt);
// "5 days ago"

const futureDate = new Date('2024-12-30');
const future = formatDistanceToNow(futureDate);
// "in 5 days"
```

### 4. Number Utilities (`number/`)

#### currency - Currency Formatting

```typescript
import { currency } from '@delon/util/number';

// Format as currency
currency(1234567.89);              // "$1,234,567.89"
currency(1234567.89, { unit: '¥' }); // "¥1,234,567.89"
currency(1234.5, { precision: 0 });  // "$1,235"
```

#### Other Number Functions

```typescript
import { 
  toFixed,      // Round to fixed decimals
  toPercent,    // Convert to percentage
  toThousands   // Add thousands separators
} from '@delon/util/number';

toFixed(1.2345, 2);           // "1.23"
toPercent(0.1234);            // "12.34%"
toPercent(0.1234, 1);         // "12.3%"
toThousands(1234567);         // "1,234,567"
```

### 5. Browser Utilities (`browser/`)

#### copyToClipboard - Copy to Clipboard

```typescript
import { copy } from '@delon/util/browser';

async copyTaskLink(taskId: string) {
  const link = `${window.location.origin}/tasks/${taskId}`;
  const success = await copy(link);
  
  if (success) {
    this.messageService.success('連結已複製');
  } else {
    this.messageService.error('複製失敗');
  }
}
```

#### Other Browser Functions

```typescript
import { 
  scrollToTop,    // Smooth scroll to top
  deepGet,        // Get nested object property
  deepSet,        // Set nested object property
  isEmpty,        // Check if value is empty
  isEqual,        // Deep equality check
  updateHostClass // Update host element classes
} from '@delon/util/browser';

scrollToTop();
scrollToTop({ duration: 500 });

const value = deepGet(obj, 'user.profile.name');
deepSet(obj, 'user.profile.name', 'New Name');

isEmpty(null);      // true
isEmpty('');        // true
isEmpty([]);        // true
isEmpty({});        // true

isEqual({ a: 1 }, { a: 1 }); // true
```

## Real-World Examples

### Task Management Utilities

```typescript
import { Component, signal, computed, inject } from '@angular/core';
import { deepCopy, groupBy, orderBy } from '@delon/util/array';
import { format } from '@delon/util/string';
import { getTimeDistance } from '@delon/util/date';
import { copy } from '@delon/util/browser';
import { NzMessageService } from 'ng-zorro-antd/message';

@Component({
  selector: 'app-task-list',
  standalone: true,
  template: `
    <nz-card>
      <div nz-row [nzGutter]="16">
        @for (group of groupedTasks() | keyvalue; track group.key) {
          <div nz-col [nzSpan]="8">
            <h3>{{ group.key }} ({{ group.value.length }})</h3>
            @for (task of group.value; track task.id) {
              <nz-card>
                <h4>{{ task.title }}</h4>
                <p>{{ formatTaskInfo(task) }}</p>
                <button nz-button (click)="copyTaskLink(task.id)">
                  複製連結
                </button>
              </nz-card>
            }
          </div>
        }
      </div>
    </nz-card>
  `
})
export class TaskListComponent {
  private messageService = inject(NzMessageService);
  
  // Original tasks from service
  tasks = signal<Task[]>([]);
  
  // Group tasks by status using @delon/util
  groupedTasks = computed(() => 
    groupBy(this.sortedTasks(), 'status')
  );
  
  // Sort tasks by priority and date
  sortedTasks = computed(() => 
    orderBy(
      this.tasks(),
      ['priority', 'createdAt'],
      ['asc', 'desc']
    )
  );
  
  // Format task information
  formatTaskInfo(task: Task): string {
    return format(
      '優先級: {priority}, 建立於 {date}',
      {
        priority: task.priority,
        date: this.formatDate(task.createdAt)
      }
    );
  }
  
  // Copy task link to clipboard
  async copyTaskLink(taskId: string): Promise<void> {
    const link = `${window.location.origin}/tasks/${taskId}`;
    const success = await copy(link);
    
    if (success) {
      this.messageService.success('任務連結已複製');
    } else {
      this.messageService.error('複製失敗,請手動複製');
    }
  }
  
  // Clone task for editing
  cloneTaskForEdit(task: Task): Task {
    return deepCopy(task);
  }
  
  // Get this week's tasks
  getThisWeekTasks(): Task[] {
    const [start, end] = getTimeDistance('week');
    return this.tasks().filter(t => 
      t.createdAt >= start && t.createdAt <= end
    );
  }
  
  private formatDate(date: Date): string {
    return format(
      '{year}-{month}-{day}',
      {
        year: date.getFullYear(),
        month: String(date.getMonth() + 1).padStart(2, '0'),
        day: String(date.getDate()).padStart(2, '0')
      }
    );
  }
}
```

### Form Data Utilities

```typescript
import { Component, signal } from '@angular/core';
import { deepCopy, deepMerge } from '@delon/util/array';
import { isEmpty } from '@delon/util/browser';

@Component({
  selector: 'app-task-form',
  standalone: true,
  template: `
    <form nz-form (ngSubmit)="handleSubmit()">
      <!-- form fields -->
      <button nz-button [disabled]="hasEmptyRequired()">
        提交
      </button>
    </form>
  `
})
export class TaskFormComponent {
  // Default form values
  private defaults = {
    priority: 'medium',
    status: 'pending',
    assignee: null,
    tags: []
  };
  
  // Form data with defaults
  formData = signal(deepCopy(this.defaults));
  
  // Original task (for editing)
  originalTask = signal<Task | null>(null);
  
  // Load task for editing
  loadTask(task: Task): void {
    // Merge task data with defaults
    const merged = deepMerge(this.defaults, task);
    this.formData.set(merged);
    this.originalTask.set(deepCopy(task));
  }
  
  // Check if required fields are empty
  hasEmptyRequired(): boolean {
    const data = this.formData();
    return isEmpty(data.title) || isEmpty(data.assignee);
  }
  
  // Check if form has changes
  hasChanges(): boolean {
    const original = this.originalTask();
    if (!original) return true;
    
    return !isEqual(original, this.formData());
  }
  
  handleSubmit(): void {
    if (!this.hasEmptyRequired()) {
      // Create clean copy for submission
      const submitData = deepCopy(this.formData());
      // Submit...
    }
  }
}
```

## Best Practices

### 1. Use Utilities for Immutability

✅ **DO**:
```typescript
const taskCopy = deepCopy(task);
taskCopy.status = 'completed';
this.tasks.update(tasks => [...tasks, taskCopy]);
```

❌ **DON'T**:
```typescript
task.status = 'completed';
this.tasks.update(tasks => [...tasks, task]); // Mutates original
```

### 2. Leverage Computed Signals with Utilities

✅ **DO**:
```typescript
groupedTasks = computed(() => groupBy(this.tasks(), 'status'));
sortedTasks = computed(() => orderBy(this.tasks(), ['priority'], ['asc']));
```

### 3. Use Type-Safe Utilities

✅ **DO**:
```typescript
import { deepCopy } from '@delon/util/array';

const copy: Task = deepCopy<Task>(originalTask);
```

## Performance Considerations

1. **deepCopy**: Expensive for large objects - use sparingly
2. **groupBy/orderBy**: Wrap in computed() to avoid recalculation
3. **getTimeDistance**: Cache results if used frequently
4. **copy**: Async operation - handle loading states

## Integration Checklist

- [ ] Install @delon/util@20.1.0
- [ ] Import specific utilities (tree-shaking friendly)
- [ ] Use with Angular Signals for reactivity
- [ ] Add TypeScript generics for type safety
- [ ] Handle async operations (copy)
- [ ] Test edge cases (null, undefined, empty)

## Cross-References

- **angular-component** - Signals integration
- **delon-form** - Form utilities for validation
- **firebase-repository** - deepCopy for state management

---

**Version**: 1.0  
**Created**: 2025-12-25  
**Maintainer**: ng-events(GigHub) Development Team

Related Skills

delon-form-dynamic-schema-forms

242
from aiskillstore/marketplace

Create dynamic schema-based forms using @delon/form (SF component). Use this skill when building complex forms with validation, conditional rendering, async data loading, custom widgets, and multi-step workflows. Ensures forms follow JSON Schema standards, integrate with Angular reactive forms, support internationalization, and maintain consistent validation patterns across the application.

delon-chart

242
from aiskillstore/marketplace

@delon/chart skill - G2Plot enterprise charting components with @delon/chart. For ng-events construction site progress tracking system.

delon-cache-caching-strategies

242
from aiskillstore/marketplace

Implement caching strategies using @delon/cache. Use this skill when adding memory cache, LocalStorage cache, SessionStorage cache, or cache interceptors for HTTP requests. Supports TTL-based expiration, cache invalidation, cache grouping, and persistent storage. Optimizes performance by reducing redundant API calls and database queries.

delon-auth-authentication-authorization

242
from aiskillstore/marketplace

Implement authentication and authorization using @delon/auth. Use this skill when adding login/logout flows, JWT token management, role-based access control (RBAC), route guards, HTTP interceptors, and session management. Integrates with Firebase Auth and custom permission systems. Ensures secure token storage, automatic token refresh, and consistent authorization checks across components and services.

delon-acl

242
from aiskillstore/marketplace

@delon/acl skill - Access Control List for role-based permissions and UI element visibility. For ng-events construction site progress tracking system.

writing-utils

240
from aiskillstore/marketplace

Use this skill when you need to write utility functions for the Next.js app

azure-quotas

242
from aiskillstore/marketplace

Check/manage Azure quotas and usage across providers. For deployment planning, capacity validation, region selection. WHEN: "check quotas", "service limits", "current usage", "request quota increase", "quota exceeded", "validate capacity", "regional availability", "provisioning limits", "vCPU limit", "how many vCPUs available in my subscription".

DevOps & Infrastructure

raindrop-io

242
from aiskillstore/marketplace

Manage Raindrop.io bookmarks with AI assistance. Save and organize bookmarks, search your collection, manage reading lists, and organize research materials. Use when working with bookmarks, web research, reading lists, or when user mentions Raindrop.io.

Data & Research

zlibrary-to-notebooklm

242
from aiskillstore/marketplace

自动从 Z-Library 下载书籍并上传到 Google NotebookLM。支持 PDF/EPUB 格式,自动转换,一键创建知识库。

discover-skills

242
from aiskillstore/marketplace

当你发现当前可用的技能都不够合适(或用户明确要求你寻找技能)时使用。本技能会基于任务目标和约束,给出一份精简的候选技能清单,帮助你选出最适配当前任务的技能。

web-performance-seo

242
from aiskillstore/marketplace

Fix PageSpeed Insights/Lighthouse accessibility "!" errors caused by contrast audit failures (CSS filters, OKLCH/OKLAB, low opacity, gradient text, image backgrounds). Use for accessibility-driven SEO/performance debugging and remediation.

project-to-obsidian

242
from aiskillstore/marketplace

将代码项目转换为 Obsidian 知识库。当用户提到 obsidian、项目文档、知识库、分析项目、转换项目 时激活。 【激活后必须执行】: 1. 先完整阅读本 SKILL.md 文件 2. 理解 AI 写入规则(默认到 00_Inbox/AI/、追加式、统一 Schema) 3. 执行 STEP 0: 使用 AskUserQuestion 询问用户确认 4. 用户确认后才开始 STEP 1 项目扫描 5. 严格按 STEP 0 → 1 → 2 → 3 → 4 顺序执行 【禁止行为】: - 禁止不读 SKILL.md 就开始分析项目 - 禁止跳过 STEP 0 用户确认 - 禁止直接在 30_Resources 创建(先到 00_Inbox/AI/) - 禁止自作主张决定输出位置