๐Ÿ‘‰๊ฒ€์ƒ‰๋ฐ”๋Š” ์•ฑ ๋‚ด์—์„œ ๊ฒ€์ƒ‰์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“  input box์ž…๋‹ˆ๋‹ค.

1. react-native-freelifemakers-ui NPM Module Install

npm install react-native-freelifemakers-ui

2.์˜์กด์„ฑ ๋ชจ๋“ˆ ์„ค์น˜ํ•˜๊ธฐ

โœ”๏ธ๋ชจ๋“ˆ๋‚ด์— package.jsonํŒŒ์ผ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ peerDependencies๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

โœ”๏ธ npm ๋ช…๋ น์–ด๋กœ ์„ค์น˜ ํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

โœ”๏ธ FlmSearchBar๋Š” react-native-vector-icons ๋ชจ๋“ˆ์ด ์„ค์น˜๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

โœ”๏ธreact-native-vector-icons์„ค์น˜ ๋ฒ„์ „์€ ์ตœ์‹ ๋ฒ„์ „ ์„ค์น˜ ํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

  "peerDependencies": {
    "react": "*",
    "react-native": "*",
    "react-native-gesture-handler": ">=2.12.0",
    "react-native-reanimated": ">=3.17.0",
    "react-native-vector-icons": ">=10.2.0"
  },

2.์‚ฌ์šฉ๋ฒ•

โœ”๏ธ๋ณผ๋“œ์™€ย ์ดํ…”๋ฆญ์ฒด๋กœ ๊ฐ•์กฐ๋œ ๋ถ€๋ถ„์ด FlmSearchBar ์ž…๋‹ˆ๋‹ค.

import React, { useState } from "react";
import {
  View,
  Text,
  StyleSheet,
  SafeAreaView,
  ScrollView,
  Alert,
} from "react-native";

import {
  ***FlmSearchBar,***
  FlmButton,
  FlmText,
} from "react-native-freelifemakers-ui";

export default function FlmSearchBarApp() {
  const [searchText, setSearchText] = useState("");

  // 
  // Search submission handler
  const handleSearchSubmit = () => {
    console.log("๊ฒ€์ƒ‰ ์ œ์ถœ/Submit Search:", searchText);
    // ์‹ค์ œ ๊ฒ€์ƒ‰ ๋กœ์ง์„ ์—ฌ๊ธฐ์— ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
    // Implement the actual search logic here.
    Alert.alert(
      `๊ฒ€์ƒ‰ ์ œ์ถœ/Submit Search`,
      `'${searchText}'(์œผ)๋กœ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค./Search for '${searchText}'.`,
    );
  };

  // ๊ฒ€์ƒ‰์–ด ์ง€์šฐ๊ธฐ ํ•ธ๋“ค๋Ÿฌ
  // Clear search term handler
  const handleClearSearch = () => {
    console.log("๊ฒ€์ƒ‰์–ด ์ง€์šฐ๊ธฐ/Clear search term");
    // ๊ฒ€์ƒ‰์–ด ์ง€์šฐ๊ธฐ ์‹œ ์ถ”๊ฐ€์ ์ธ ๋กœ์ง์ด ํ•„์š”ํ•˜๋ฉด ์—ฌ๊ธฐ์— ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
    // If additional logic is needed when clearing search terms, implement it here.
    Alert.alert(
      `๊ฒ€์ƒ‰์–ด ์ง€์šฐ๊ธฐ/Clear search term`,
      `๊ฒ€์ƒ‰์–ด๊ฐ€ ์ง€์›Œ์กŒ์Šต๋‹ˆ๋‹ค./Your search term has been cleared.`,
    );
  };

  return (
    <SafeAreaView>
      <ScrollView>
  

        ***<FlmSearchBar
          value={searchText}
          onChangeText={setSearchText}
          placeholder="์—ฌ๊ธฐ์— ๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”/Enter your search term here"
          onSubmitEditing={handleSearchSubmit}
          onClear={handleClearSearch}
          style={styles.searchBarMargin}
        />***

      </ScrollView>
    </SafeAreaView>
  );
 }

}

3.์ „์ฒด์ฝ”๋“œ

โœ”๏ธ์•„๋ž˜์˜ ์ฝ”๋“œ์—์„œย **import Ionicons from โ€˜react-native-vector-icons/Ioniconsโ€™;**์ด ๋ถ€๋ถ„์€ ReactNative CLI์—๋งŒ ํ•ด๋‹น๋ฉ๋‹ˆ๋‹ค. โœ”๏ธ์—‘์Šคํฌ ์‚ฌ์šฉ์ž๋Š” ์œ„์˜ ์ฝ”๋“œ๋ฅผ ์ฃผ์„์ฒ˜๋ฆฌ ํ•ด์ฃผ์„ธ์š”

// flmSearchBar.js
import React, {useState} from 'react';
import {
  View,
  Text,
  StyleSheet,
  SafeAreaView,
  ScrollView,
  Alert,
} from 'react-native';

// ReactNative CLI์ธ๊ฒฝ์šฐ
// npm install react-native-vector-icons
import Ionicons from 'react-native-vector-icons/Ionicons';
// Expo๋Š” react-native-vector-icons๋ฅผ ๋‚ด์žฅํ•˜๊ณ  ์žˆ์Œ
// Expo includes react-native-vector-icons by default.
// import {Ionicons} from '@expo/vector-icons';

// react-native-freelifemakers-ui ํŒจํ‚ค์ง€์—์„œ FlmSearchBar ์ž„ํฌํŠธ
import {FlmSearchBar, FlmButton, FlmText} from 'react-native-freelifemakers-ui';

export default function FlmSearchBarApp() {
  const [searchText, setSearchText] = useState('');

  // ๊ฒ€์ƒ‰ ์ œ์ถœ ํ•ธ๋“ค๋Ÿฌ
  // Search submission handler
  const handleSearchSubmit = () => {
    console.log('๊ฒ€์ƒ‰ ์ œ์ถœ/Submit Search:', searchText);
    // ์‹ค์ œ ๊ฒ€์ƒ‰ ๋กœ์ง์„ ์—ฌ๊ธฐ์— ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
    // Implement the actual search logic here.
    Alert.alert(
      `๊ฒ€์ƒ‰ ์ œ์ถœ/Submit Search`,
      `'${searchText}'(์œผ)๋กœ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค./Search for '${searchText}'.`,
    );
  };

  // ๊ฒ€์ƒ‰์–ด ์ง€์šฐ๊ธฐ ํ•ธ๋“ค๋Ÿฌ
  // Clear search term handler
  const handleClearSearch = () => {
    console.log('๊ฒ€์ƒ‰์–ด ์ง€์šฐ๊ธฐ/Clear search term');
    // ๊ฒ€์ƒ‰์–ด ์ง€์šฐ๊ธฐ ์‹œ ์ถ”๊ฐ€์ ์ธ ๋กœ์ง์ด ํ•„์š”ํ•˜๋ฉด ์—ฌ๊ธฐ์— ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
    // If additional logic is needed when clearing search terms, implement it here.
    Alert.alert(
      `๊ฒ€์ƒ‰์–ด ์ง€์šฐ๊ธฐ/Clear search term`,
      `๊ฒ€์ƒ‰์–ด๊ฐ€ ์ง€์›Œ์กŒ์Šต๋‹ˆ๋‹ค./Your search term has been cleared.`,
    );
  };

  return (
    <SafeAreaView style={styles.safeArea}>
      <ScrollView contentContainerStyle={styles.scrollViewContent}>
        <Text style={styles.header}>FlmSearchBar</Text>
        {/* ๊ธฐ๋ณธ ๊ฒ€์ƒ‰ ๋ฐ” / Default Search Bar */}
        <FlmText style={styles.subHeader}>
          ๊ธฐ๋ณธ ๊ฒ€์ƒ‰ ๋ฐ” / Default Search Bar
        </FlmText>
        <FlmSearchBar
          value={searchText}
          onChangeText={setSearchText}
          placeholder="์—ฌ๊ธฐ์— ๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”/Enter your search term here"
          onSubmitEditing={handleSearchSubmit}
          onClear={handleClearSearch}
          style={styles.searchBarMargin}
        />
        <FlmText style={styles.currentSearchText}>
          ํ˜„์žฌ ๊ฒ€์ƒ‰์–ด/ Current search term: {searchText || '์—†์Œ/none'}
        </FlmText>
        {/* ์ปค์Šคํ„ฐ๋งˆ์ด์ง•๋œ ๊ฒ€์ƒ‰ ๋ฐ” ์˜ˆ์‹œ / Example of a customized search bar */}
        <FlmText style={styles.subHeader}>
          ์ปค์Šคํ…€ ์Šคํƒ€์ผ ๊ฒ€์ƒ‰ ๋ฐ” / Custom style search bar
        </FlmText>
        <FlmSearchBar
          value={searchText}
          onChangeText={setSearchText}
          placeholder="๋‹ค๋ฅธ ์Šคํƒ€์ผ์˜ ๊ฒ€์ƒ‰ ๋ฐ”/Search bar in different styles"
          placeholderTextColor="#aaa"
          style={styles.customSearchBar}
          inputStyle={styles.customInput}
          showClearButton={false} // ์ง€์šฐ๊ธฐ ๋ฒ„ํŠผ ์ˆจ๊ธฐ๊ธฐ / Hide the erase button
        />
        {/* ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์™€์˜ ์กฐํ•ฉ ์˜ˆ์‹œ / Example of combination with other components */}
        <FlmText style={styles.subHeader}>
          ๋ฒ„ํŠผ๊ณผ ํ•จ๊ป˜ ๊ฒ€์ƒ‰ / Search with button
        </FlmText>
        <FlmSearchBar
          value={searchText}
          onChangeText={setSearchText}
          placeholder="๋ฒ„ํŠผ๊ณผ ํ•จ๊ป˜ ๊ฒ€์ƒ‰/Search with button"
          onSubmitEditing={handleSearchSubmit}
          keyboardType="web-search"
        />
        <FlmButton
          title="๊ฒ€์ƒ‰ ์‹คํ–‰/Run search"
          onPress={handleSearchSubmit}
          style={styles.searchButton}
        />
        {/* ํ•˜๋‹จ ์—ฌ๋ฐฑ / bottom margin */}
        <View style={{height: 50}} />
      </ScrollView>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  safeArea: {
    flex: 1,
    backgroundColor: '#f8f8f8',
  },
  scrollViewContent: {
    flexGrow: 1,
    paddingVertical: 20,
    alignItems: 'center',
  },
  header: {
    fontSize: 28,
    fontWeight: 'bold',
    marginBottom: 30,
    color: '#333',
  },
  subHeader: {
    fontSize: 20,
    fontWeight: '600',
    marginTop: 30,
    marginBottom: 15,
    color: '#555',
  },
  searchBarMargin: {
    marginBottom: 20,
  },
  currentSearchText: {
    fontSize: 16,
    color: '#666',
    marginBottom: 20,
  },
  customSearchBar: {
    backgroundColor: '#e0f7fa', // ๋ฐ์€ ํŒŒ๋ž€์ƒ‰ ๋ฐฐ๊ฒฝ / light blue background
    borderRadius: 10,
    borderWidth: 1,
    borderColor: '#b2ebf2',
    height: 45,
    marginVertical: 10,
  },
  customInput: {
    color: '#00796b', // ์ง„ํ•œ ์ฒญ๋ก์ƒ‰ ํ…์ŠคํŠธ / Dark turquoise text
    fontWeight: 'bold',
  },
  searchButton: {
    marginTop: 10,
    backgroundColor: '#007bff',
  },
});