npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@libs-ui/components-buttons-select-color

v0.2.357-11

Published

> Button tích hợp color picker dạng popover, hỗ trợ chế độ apply ngay hoặc apply sau khi xác nhận.

Readme

@libs-ui/components-buttons-select-color

Button tích hợp color picker dạng popover, hỗ trợ chế độ apply ngay hoặc apply sau khi xác nhận.

Giới thiệu

LibsUiComponentsButtonsSelectColorComponent là standalone Angular component hiển thị một button mở popover chứa color picker. Component hỗ trợ hai chế độ: applyNow = true để emit màu ngay khi chọn, hoặc applyNow = false để hiển thị nút Cancel / Apply trước khi xác nhận. Màu có thể được emit dưới dạng chuỗi đơn (outColorChange) hoặc object chứa tất cả định dạng (outColorChangeMultipleType).

Tính năng

  • ✅ Hai chế độ: Apply ngay (applyNow = true) hoặc Apply sau qua nút xác nhận (applyNow = false)
  • ✅ Emit màu dưới nhiều định dạng: HEX, RGB, RGBA, HSL, HSLA, Alpha
  • ✅ Tùy chỉnh button trigger qua IButton (label, icon, type, disabled...)
  • ✅ Hỗ trợ external content — dùng bất kỳ element nào làm trigger thay cho button mặc định
  • ✅ Tùy chỉnh color picker options (màu khởi tạo, hiển thị formats, alpha slider...)
  • ✅ Điều hướng popover 4 chiều: top, bottom, left, right
  • ✅ Two-way binding cho zIndex tránh xung đột với modal/dialog khác
  • ✅ Tự động cleanup popover khi component bị destroy
  • ✅ OnPush Change Detection + Angular Signals

Khi nào sử dụng

  • Cho phép user chọn màu trong các tính năng theme customization, color settings
  • Tích hợp color picker vào toolbar, design tool, form nhập màu sắc
  • Khi cần preview màu trước khi confirm (applyNow = false)
  • Khi cần hiển thị một color swatch làm trigger thay cho button thông thường (externalContent = true)

Cài đặt

npm install @libs-ui/components-buttons-select-color

Import

import { LibsUiComponentsButtonsSelectColorComponent } from '@libs-ui/components-buttons-select-color';
import { IOutputColorChangeMultipleType, IPickerCustomOptions } from '@libs-ui/components-color-picker';
import { IButton } from '@libs-ui/components-buttons-button';

@Component({
  standalone: true,
  imports: [LibsUiComponentsButtonsSelectColorComponent],
})
export class MyComponent {}

Ví dụ sử dụng

1. Apply ngay khi chọn màu

<!-- template.html -->
<libs_ui-components-buttons-select_color
  [button]="{ label: 'Select Color', type: 'button-primary' }"
  [applyNow]="true"
  (outColorChange)="handlerColorChange($event)"
/>

<div [style.background-color]="selectedColor()" class="w-24 h-8 rounded mt-4">
  {{ selectedColor() }}
</div>
// component.ts
import { Component, signal } from '@angular/core';
import { LibsUiComponentsButtonsSelectColorComponent } from '@libs-ui/components-buttons-select-color';

@Component({
  standalone: true,
  imports: [LibsUiComponentsButtonsSelectColorComponent],
})
export class MyComponent {
  protected selectedColor = signal<string>('#3b82f6');

  protected handlerColorChange(event: string): void {
    event.stopPropagation?.();
    this.selectedColor.set(event);
  }
}

2. Chọn trước, bấm Apply sau + nhận nhiều định dạng màu

<!-- template.html -->
<libs_ui-components-buttons-select_color
  [button]="{ label: 'Choose Color', type: 'button-secondary' }"
  [applyNow]="false"
  (outColorChange)="handlerColorChange($event)"
  (outColorChangeMultipleType)="handlerColorChangeMultipleType($event)"
/>
// component.ts
import { Component, signal } from '@angular/core';
import { LibsUiComponentsButtonsSelectColorComponent } from '@libs-ui/components-buttons-select-color';
import { IOutputColorChangeMultipleType } from '@libs-ui/components-color-picker';

@Component({
  standalone: true,
  imports: [LibsUiComponentsButtonsSelectColorComponent],
})
export class MyComponent {
  protected selectedColor = signal<string>('#10b981');
  protected colorFormats = signal<IOutputColorChangeMultipleType | null>(null);

  protected handlerColorChange(event: string): void {
    this.selectedColor.set(event);
  }

  protected handlerColorChangeMultipleType(event: IOutputColorChangeMultipleType): void {
    this.colorFormats.set(event);
    // event.hex   → '#10b981'
    // event.rgb   → 'rgb(16, 185, 129)'
    // event.rgba  → 'rgba(16, 185, 129, 1)'
    // event.hsl   → 'hsl(160, 84%, 39%)'
    // event.hsla  → 'hsla(160, 84%, 39%, 1)'
    // event.alpha → 1
  }
}

3. Tùy chỉnh color picker options

<!-- template.html -->
<libs_ui-components-buttons-select_color
  [button]="{ label: 'Pick Color', type: 'button-secondary', classIconLeft: 'libs-ui-icon-editor-color-background' }"
  [customOptions]="customOptions"
  [applyNow]="true"
  (outColorChange)="handlerColorChange($event)"
/>
// component.ts
import { Component, signal } from '@angular/core';
import { LibsUiComponentsButtonsSelectColorComponent } from '@libs-ui/components-buttons-select-color';
import { IPickerCustomOptions } from '@libs-ui/components-color-picker';

@Component({
  standalone: true,
  imports: [LibsUiComponentsButtonsSelectColorComponent],
})
export class MyComponent {
  protected selectedColor = signal<string>('#ff5733');

  protected readonly customOptions: IPickerCustomOptions = {
    color: '#ff5733',
    showAlpha: true,
    showHex: true,
    showRgb: true,
    showHsl: true,
    format: 'hex',
  };

  protected handlerColorChange(event: string): void {
    this.selectedColor.set(event);
  }
}

4. External content — dùng color swatch làm trigger

<!-- template.html -->
<libs_ui-components-buttons-select_color
  [externalContent]="true"
  [applyNow]="true"
  (outColorChange)="handlerColorChange($event)">
  <div class="libs-ui-buttons-select-color">
    <div
      class="w-12 h-12 rounded-lg border-2 border-gray-300 cursor-pointer shadow-sm hover:shadow-md transition-shadow"
      [style.background-color]="selectedColor()">
    </div>
  </div>
</libs_ui-components-buttons-select_color>
// component.ts
import { Component, signal } from '@angular/core';
import { LibsUiComponentsButtonsSelectColorComponent } from '@libs-ui/components-buttons-select-color';

@Component({
  standalone: true,
  imports: [LibsUiComponentsButtonsSelectColorComponent],
})
export class MyComponent {
  protected selectedColor = signal<string>('#8b5cf6');

  protected handlerColorChange(event: string): void {
    this.selectedColor.set(event);
  }
}

5. Icon only button với hướng popover tùy chỉnh

<!-- template.html -->
<libs_ui-components-buttons-select_color
  [button]="{ classIconLeft: 'libs-ui-icon-editor-color-background', iconOnlyType: true }"
  [direction]="'top'"
  [applyNow]="true"
  (outColorChange)="handlerColorChange($event)"
/>
// component.ts
import { Component, signal } from '@angular/core';
import { LibsUiComponentsButtonsSelectColorComponent } from '@libs-ui/components-buttons-select-color';

@Component({
  standalone: true,
  imports: [LibsUiComponentsButtonsSelectColorComponent],
})
export class MyComponent {
  protected selectedColor = signal<string>('#3b82f6');

  protected handlerColorChange(event: string): void {
    this.selectedColor.set(event);
  }
}

6. Two-way binding zIndex tránh xung đột với modal

<!-- template.html -->
<libs_ui-components-buttons-select_color
  [button]="{ label: 'Select Color' }"
  [(zIndex)]="popoverZIndex"
  [applyNow]="true"
  (outColorChange)="handlerColorChange($event)"
/>
// component.ts
import { Component, signal } from '@angular/core';
import { LibsUiComponentsButtonsSelectColorComponent } from '@libs-ui/components-buttons-select-color';

@Component({
  standalone: true,
  imports: [LibsUiComponentsButtonsSelectColorComponent],
})
export class MyComponent {
  protected selectedColor = signal<string>('#3b82f6');
  protected popoverZIndex = 2000;

  protected handlerColorChange(event: string): void {
    this.selectedColor.set(event);
  }
}

@Input()

| Input | Type | Default | Mô tả | Ví dụ | |---|---|---|---|---| | [applyNow] | boolean | false | true: emit màu ngay khi chọn, không cần xác nhận. false: hiển thị nút Cancel / Apply, emit khi bấm Apply | [applyNow]="true" | | [button] | IButton | undefined | Cấu hình cho button trigger (label, type, icon, disabled...). Bị bỏ qua khi externalContent = true | [button]="{ label: 'Pick', type: 'button-primary' }" | | [customOptions] | IPickerCustomOptions | undefined | Tùy chỉnh color picker: màu khởi tạo, hiện/ẩn formats (hex, rgb, hsl), alpha slider, kích thước thanh slider | [customOptions]="{ color: '#ff0000', showAlpha: true, format: 'hex' }" | | [direction] | TYPE_POPOVER_DIRECTION | 'bottom' | Hướng mở popover so với trigger button | [direction]="'top'" | | [externalContent] | boolean | false | true: dùng content projection (class libs-ui-buttons-select-color) thay cho button mặc định | [externalContent]="true" | | [(zIndex)] | number | 1200 | Z-index của popover, hỗ trợ two-way binding | [(zIndex)]="myZIndex" |

@Output()

| Output | Type | Mô tả | Handler TS | Binding HTML | |---|---|---|---|---| | (outColorChange) | string | Emit màu đã chọn dưới dạng chuỗi, format theo customOptions.format (mặc định: hex). Khi applyNow = false chỉ emit khi bấm Apply | handlerColorChange(event: string): void { this.selectedColor.set(event); } | (outColorChange)="handlerColorChange($event)" | | (outColorChangeMultipleType) | IOutputColorChangeMultipleType | Emit object chứa tất cả định dạng màu (hex, rgb, rgba, hsl, hsla, alpha) cùng lúc. Khi applyNow = false chỉ emit khi bấm Apply | handlerColorChangeMultipleType(event: IOutputColorChangeMultipleType): void { this.colorFormats.set(event); } | (outColorChangeMultipleType)="handlerColorChangeMultipleType($event)" |

Types & Interfaces

import { IOutputColorChangeMultipleType, IPickerCustomOptions } from '@libs-ui/components-color-picker';
import { IButton } from '@libs-ui/components-buttons-button';
import { TYPE_POPOVER_DIRECTION } from '@libs-ui/components-popover';

IPickerCustomOptions

export interface IPickerCustomOptions {
  /** Kích thước saturation/lightness bar [width, height] */
  slBarSize?: Array<number>;

  /** Kích thước hue bar [width, height] */
  hueBarSize?: Array<number>;

  /** Kích thước alpha bar [width, height] */
  alphaBarSize?: Array<number>;

  /** Hiển thị HSL input — default: true */
  showHsl?: boolean;

  /** Hiển thị RGB input — default: true */
  showRgb?: boolean;

  /** Hiển thị HEX input — default: true */
  showHex?: boolean;

  /** Hiển thị Alpha slider — default: false */
  showAlpha?: boolean;

  /** Màu khởi tạo: HEX string hoặc RGB array */
  color?: string | Array<number>;

  /** Format chuỗi màu emit qua outColorChange */
  format?: 'rgb' | 'rgba' | 'hsl' | 'hsla' | 'hex' | 'color';
}

IOutputColorChangeMultipleType

export interface IOutputColorChangeMultipleType {
  /** Màu dạng RGBA: "rgba(255, 0, 0, 1)" */
  rgba: string;

  /** Màu dạng RGB: "rgb(255, 0, 0)" */
  rgb: string;

  /** Màu dạng HEX: "#ff0000" */
  hex: string;

  /** Màu dạng HSL: "hsl(0, 100%, 50%)" */
  hsl: string;

  /** Màu dạng HSLA: "hsla(0, 100%, 50%, 1)" */
  hsla: string;

  /** Giá trị alpha trong khoảng 0–1 */
  alpha: number;
}

TYPE_POPOVER_DIRECTION

export type TYPE_POPOVER_DIRECTION = 'top' | 'bottom' | 'left' | 'right';

IButton (các thuộc tính thường dùng)

export interface IButton {
  /** Nhãn hiển thị trên button */
  label?: string;

  /** Kiểu button: 'button-primary' | 'button-secondary' | 'button-third' | ... */
  type?: TYPE_BUTTON;

  /** Class icon bên trái */
  classIconLeft?: string;

  /** Class icon bên phải */
  classIconRight?: string;

  /** Hiển thị dạng icon only (không label) */
  iconOnlyType?: boolean;

  /** Vô hiệu hóa button */
  disable?: boolean;

  /** Class thêm vào button */
  classInclude?: string;
}

Lưu ý quan trọng

⚠️ External content selector bắt buộc: Khi dùng [externalContent]="true", wrapper div của content projection PHẢI có class libs-ui-buttons-select-color. Thiếu class này popover sẽ không mở.

<!-- ĐÚNG -->
<libs_ui-components-buttons-select_color [externalContent]="true" [applyNow]="true">
  <div class="libs-ui-buttons-select-color">
    <div class="w-10 h-10 rounded cursor-pointer" [style.background-color]="selectedColor()"></div>
  </div>
</libs_ui-components-buttons-select_color>

<!-- SAI — thiếu class libs-ui-buttons-select-color -->
<libs_ui-components-buttons-select_color [externalContent]="true" [applyNow]="true">
  <div>
    <div class="w-10 h-10 rounded cursor-pointer"></div>
  </div>
</libs_ui-components-buttons-select_color>

⚠️ Hành vi emit khi applyNow = false: Khi applyNow = false, component giữ màu đã chọn trong state nội bộ và chỉ emit outColorChange + outColorChangeMultipleType khi user bấm nút "Apply". Bấm "Cancel" đóng popover mà không emit. Bấm "Apply" cũng tự đóng popover sau khi emit.

⚠️ Format chuỗi từ outColorChange: Output outColorChange emit chuỗi theo customOptions.format. Nếu không thiết lập customOptions.format, format mặc định phụ thuộc vào color picker. Để nhận màu theo tất cả định dạng cùng lúc, dùng outColorChangeMultipleType.

⚠️ Z-index khi dùng trong modal/dialog: Default z-index là 1200. Khi component nằm bên trong modal hoặc dialog có z-index cao hơn, cần tăng [(zIndex)] lên tương ứng để popover hiển thị đúng trên cùng.

⚠️ Cleanup tự động: Component tự gọi removePopoverOverlay() trong ngOnDestroy. Không cần cleanup thủ công ở component cha.